Merge PR #422: New Plugin: ZigbeeDevelco

This commit is contained in:
Jenkins nymea 2021-07-01 17:07:07 +02:00
commit 7a3846f56a
11 changed files with 1254 additions and 1 deletions

19
debian/control vendored
View File

@ -1061,6 +1061,22 @@ Description: nymea.io plugin to monitor the ISS position
This package will install the nymea.io plugin for wheretheiss.at
Package: nymea-plugin-zigbee-develco
Architecture: any
Depends: ${shlibs:Depends},
${misc:Depends},
libnymea-zigbee1,
nymea-plugins-translations,
Description: nymea.io zigbee plugin for develco things
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package will install the nymea.io plugin for Develco
Package: nymea-plugin-zigbee-lumi
Architecture: any
Depends: ${shlibs:Depends},
@ -1215,7 +1231,8 @@ Description: Plugins for nymea IoT server - the default plugin collection
Package: nymea-plugins-zigbee
Section: libs
Architecture: all
Depends: nymea-plugin-zigbee-lumi,
Depends: nymea-plugin-zigbee-develco,
nymea-plugin-zigbee-lumi,
nymea-plugin-zigbee-generic,
nymea-plugin-zigbee-generic-lights,
nymea-plugin-zigbee-philipshue,

View File

@ -0,0 +1 @@
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginzigbeedevelco.so

View File

@ -69,6 +69,7 @@ PLUGIN_DIRS = \
wakeonlan \
wemo \
ws2812fx \
zigbeedevelco \
zigbeegeneric \
zigbeegenericlights \
zigbeelumi \

24
zigbeedevelco/README.md Normal file
View File

@ -0,0 +1,24 @@
# Develco ZigBee
This plugin allows to interact with ZigBee devices from [Develco](https://www.develcoproducts.com/).
## Supported Things
In order to bring a ZigBee device into the nymea ZigBee network, the network needs to be opened for joining before you perform the device pairing instructions. The joining process can take up to 30 seconds. If the device does not show up, please restart the pairing process.
### IO Module
The [Develco IO Module](https://www.develcoproducts.com/products/smart-relays/io-module/) is fully supported.
**Pairing instructions**: Open the ZigBee network for joining. Press and hold the reset button of the IO module until the LED blinks constanly.
### Air Quality sensor
The [Develco Air Quality sensor](https://www.develcoproducts.com/products/sensors-and-alarms/air-quality-sensor/) is fully supported.
**Pairing instructions**: Open the ZigBee network for joining. Press and hold the reset button in the sensor casing until the LED blinks constanly.
## Requirements
* A compatible ZigBee controller and a running ZigBee network in nymea. You can find more information about supported controllers and ZigBee network configurations [here](https://nymea.io/documentation/users/usage/configuration#zigbee).

BIN
zigbeedevelco/develco.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -0,0 +1,695 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
*
* Copyright 2013 - 2021, nymea GmbH
* Contact: contact@nymea.io
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; version 3. This project is distributed in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "integrationpluginzigbeedevelco.h"
#include "plugininfo.h"
#include "hardware/zigbee/zigbeehardwareresource.h"
#include <QDebug>
#include <zigbeeutils.h>
IntegrationPluginZigbeeDevelco::IntegrationPluginZigbeeDevelco()
{
m_ieeeAddressParamTypeIds[ioModuleThingClassId] = ioModuleThingIeeeAddressParamTypeId;
m_networkUuidParamTypeIds[ioModuleThingClassId] = ioModuleThingNetworkUuidParamTypeId;
m_connectedStateTypeIds[ioModuleThingClassId] = ioModuleConnectedStateTypeId;
m_signalStrengthStateTypeIds[ioModuleThingClassId] = ioModuleSignalStrengthStateTypeId;
}
QString IntegrationPluginZigbeeDevelco::name() const
{
return "Develco";
}
bool IntegrationPluginZigbeeDevelco::handleNode(ZigbeeNode *node, const QUuid &networkUuid)
{
// Filter for develco manufacturer code
if (node->nodeDescriptor().manufacturerCode != Zigbee::Develco)
return false;
bool handled = false;
if (node->modelName() == "IOMZB-110" || node->modelName() == "DIOZB-110") {
if (node->hasEndpoint(IO_MODULE_EP_INPUT1) && node->hasEndpoint(IO_MODULE_EP_INPUT2) &&
node->hasEndpoint(IO_MODULE_EP_INPUT3) && node->hasEndpoint(IO_MODULE_EP_INPUT4) &&
node->hasEndpoint(IO_MODULE_EP_OUTPUT1 && node->hasEndpoint(IO_MODULE_EP_OUTPUT2))) {
qCDebug(dcZigbeeDevelco()) << "Found IO module" << node << networkUuid.toString();
initIoModule(node);
createThing(ioModuleThingClassId, networkUuid, node);
handled = true;
}
}
return handled;
}
void IntegrationPluginZigbeeDevelco::handleRemoveNode(ZigbeeNode *node, const QUuid &networkUuid)
{
Q_UNUSED(networkUuid)
Thing *thing = m_thingNodes.key(node);
if (thing) {
qCDebug(dcZigbeeDevelco()) << node << "for" << thing << "has left the network.";
emit autoThingDisappeared(thing->id());
// Removing it from our map to prevent a loop that would ask the zigbee network to remove this node (see thingRemoved())
m_thingNodes.remove(thing);
}
}
void IntegrationPluginZigbeeDevelco::init()
{
hardwareManager()->zigbeeResource()->registerHandler(this, ZigbeeHardwareResource::HandlerTypeVendor);
}
void IntegrationPluginZigbeeDevelco::setupThing(ThingSetupInfo *info)
{
qCDebug(dcZigbeeDevelco()) << "Setup" << info->thing();
// Get the node for this thing
Thing *thing = info->thing();
QUuid networkUuid = thing->paramValue(m_networkUuidParamTypeIds.value(thing->thingClassId())).toUuid();
ZigbeeAddress zigbeeAddress = ZigbeeAddress(thing->paramValue(m_ieeeAddressParamTypeIds.value(thing->thingClassId())).toString());
ZigbeeNode *node = m_thingNodes.value(thing);
if (!node) {
node = hardwareManager()->zigbeeResource()->claimNode(this, networkUuid, zigbeeAddress);
if (!node) {
qCWarning(dcZigbeeDevelco()) << "Coud not find zigbee node for" << thing;
info->finish(Thing::ThingErrorHardwareNotAvailable);
return;
}
}
m_thingNodes.insert(thing, node);
// Update signal strength
thing->setStateValue(m_signalStrengthStateTypeIds.value(thing->thingClassId()), qRound(node->lqi() * 100.0 / 255.0));
connect(node, &ZigbeeNode::lqiChanged, thing, [this, thing](quint8 lqi){
uint signalStrength = qRound(lqi * 100.0 / 255.0);
qCDebug(dcZigbeeDevelco()) << thing << "signal strength changed" << signalStrength << "%";
thing->setStateValue(m_signalStrengthStateTypeIds.value(thing->thingClassId()), signalStrength);
});
if (thing->thingClassId() == ioModuleThingClassId) {
// Set the version from the manufacturer specific attribute in base cluster
ZigbeeNodeEndpoint *primaryEndpoint = node->getEndpoint(IO_MODULE_EP_INPUT1);
if (!primaryEndpoint) {
qCWarning(dcZigbeeDevelco()) << "Failed to set up IO module" << thing << ". Could not find endpoint for version parsing.";
info->finish(Thing::ThingErrorSetupFailed);
return;
}
if (primaryEndpoint->hasInputCluster(ZigbeeClusterLibrary::ClusterIdBasic)) {
ZigbeeCluster *basicCluster = primaryEndpoint->getInputCluster(ZigbeeClusterLibrary::ClusterIdBasic);
if (basicCluster->hasAttribute(DEVELCO_ATTRIBUTE_SW_VERSION)) {
thing->setStateValue(ioModuleVersionStateTypeId, parseDevelcoVersionString(primaryEndpoint));
} else {
readDevelcoFirmwareVersion(node, primaryEndpoint);
}
connect(basicCluster, &ZigbeeCluster::attributeChanged, this, [=](const ZigbeeClusterAttribute &attribute){
if (attribute.id() == DEVELCO_ATTRIBUTE_SW_VERSION) {
thing->setStateValue(ioModuleVersionStateTypeId, parseDevelcoVersionString(primaryEndpoint));
}
});
}
// Handle reachable state from node
thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), node->reachable());
connect(node, &ZigbeeNode::reachableChanged, thing, [=](bool reachable){
thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), reachable);
if (reachable) {
readDevelcoFirmwareVersion(node, node->getEndpoint(IO_MODULE_EP_INPUT1));
readIoModuleOutputPowerStates(thing);
readIoModuleInputPowerStates(thing);
}
});
// Output 1
ZigbeeNodeEndpoint *output1Endpoint = node->getEndpoint(IO_MODULE_EP_OUTPUT1);
if (!output1Endpoint) {
qCWarning(dcZigbeeDevelco()) << "Could not find endpoint for output 1 on" << thing << node;
} else {
ZigbeeClusterOnOff *onOffCluster = output1Endpoint->inputCluster<ZigbeeClusterOnOff>(ZigbeeClusterLibrary::ClusterIdOnOff);
if (!onOffCluster) {
qCWarning(dcZigbeeDevelco()) << "Could not find On/Off cluster on" << thing << node << output1Endpoint;
} else {
if (onOffCluster->hasAttribute(ZigbeeClusterOnOff::AttributeOnOff)) {
thing->setStateValue(ioModuleOutput1StateTypeId, onOffCluster->power());
}
connect(onOffCluster, &ZigbeeClusterOnOff::powerChanged, thing, [thing](bool power){
qCDebug(dcZigbeeDevelco()) << thing << "output 1 power changed to" << power;
thing->setStateValue(ioModuleOutput1StateTypeId, power);
});
}
}
// Output 2
ZigbeeNodeEndpoint *output2Endpoint = node->getEndpoint(IO_MODULE_EP_OUTPUT2);
if (!output2Endpoint) {
qCWarning(dcZigbeeDevelco()) << "Could not find endpoint for output 2 on" << thing << node;
} else {
ZigbeeClusterOnOff *onOffCluster = output2Endpoint->inputCluster<ZigbeeClusterOnOff>(ZigbeeClusterLibrary::ClusterIdOnOff);
if (!onOffCluster) {
qCWarning(dcZigbeeDevelco()) << "Could not find On/Off cluster on" << thing << node << output2Endpoint;
} else {
if (onOffCluster->hasAttribute(ZigbeeClusterOnOff::AttributeOnOff)) {
thing->setStateValue(ioModuleOutput2StateTypeId, onOffCluster->power());
}
connect(onOffCluster, &ZigbeeClusterOnOff::powerChanged, thing, [thing](bool power){
qCDebug(dcZigbeeDevelco()) << thing << "output 2 power changed to" << power;
thing->setStateValue(ioModuleOutput2StateTypeId, power);
});
}
}
// Input 1
ZigbeeNodeEndpoint *input1Endpoint = node->getEndpoint(IO_MODULE_EP_INPUT1);
if (!input1Endpoint) {
qCWarning(dcZigbeeDevelco()) << "Could not find endpoint for input 1 on" << thing << node;
} else {
ZigbeeClusterBinaryInput *binaryInputCluster = input1Endpoint->inputCluster<ZigbeeClusterBinaryInput>(ZigbeeClusterLibrary::ClusterIdBinaryInput);
if (!binaryInputCluster) {
qCWarning(dcZigbeeDevelco()) << "Could not find BinaryInput cluster on" << thing << node << input1Endpoint;
} else {
if (binaryInputCluster->hasAttribute(ZigbeeClusterLibrary::ClusterIdBinaryInput)) {
thing->setStateValue(ioModuleInput1StateTypeId, binaryInputCluster->presentValue());
}
connect(binaryInputCluster, &ZigbeeClusterBinaryInput::presentValueChanged, thing, [thing](bool presentValue){
qCDebug(dcZigbeeDevelco()) << thing << "input 1 changed to" << presentValue;
thing->setStateValue(ioModuleInput1StateTypeId, presentValue);
});
}
}
// Input 2
ZigbeeNodeEndpoint *input2Endpoint = node->getEndpoint(IO_MODULE_EP_INPUT2);
if (!input2Endpoint) {
qCWarning(dcZigbeeDevelco()) << "Could not find endpoint for input 2 on" << thing << node;
} else {
ZigbeeClusterBinaryInput *binaryInputCluster = input2Endpoint->inputCluster<ZigbeeClusterBinaryInput>(ZigbeeClusterLibrary::ClusterIdBinaryInput);
if (!binaryInputCluster) {
qCWarning(dcZigbeeDevelco()) << "Could not find BinaryInput cluster on" << thing << node << input2Endpoint;
} else {
if (binaryInputCluster->hasAttribute(ZigbeeClusterLibrary::ClusterIdBinaryInput)) {
thing->setStateValue(ioModuleInput2StateTypeId, binaryInputCluster->presentValue());
}
connect(binaryInputCluster, &ZigbeeClusterBinaryInput::presentValueChanged, thing, [thing](bool presentValue){
qCDebug(dcZigbeeDevelco()) << thing << "input 2 changed to" << presentValue;
thing->setStateValue(ioModuleInput2StateTypeId, presentValue);
});
}
}
// Input 3
ZigbeeNodeEndpoint *input3Endpoint = node->getEndpoint(IO_MODULE_EP_INPUT3);
if (!input3Endpoint) {
qCWarning(dcZigbeeDevelco()) << "Could not find endpoint for input 3 on" << thing << node;
} else {
ZigbeeClusterBinaryInput *binaryInputCluster = input3Endpoint->inputCluster<ZigbeeClusterBinaryInput>(ZigbeeClusterLibrary::ClusterIdBinaryInput);
if (!binaryInputCluster) {
qCWarning(dcZigbeeDevelco()) << "Could not find BinaryInput cluster on" << thing << node << input3Endpoint;
} else {
if (binaryInputCluster->hasAttribute(ZigbeeClusterLibrary::ClusterIdBinaryInput)) {
thing->setStateValue(ioModuleInput3StateTypeId, binaryInputCluster->presentValue());
}
connect(binaryInputCluster, &ZigbeeClusterBinaryInput::presentValueChanged, thing, [thing](bool presentValue){
qCDebug(dcZigbeeDevelco()) << thing << "input 3 changed to" << presentValue;
thing->setStateValue(ioModuleInput3StateTypeId, presentValue);
});
}
}
// Input 4
ZigbeeNodeEndpoint *input4Endpoint = node->getEndpoint(IO_MODULE_EP_INPUT4);
if (!input4Endpoint) {
qCWarning(dcZigbeeDevelco()) << "Could not find endpoint for input 4 on" << thing << node;
} else {
ZigbeeClusterBinaryInput *binaryInputCluster = input4Endpoint->inputCluster<ZigbeeClusterBinaryInput>(ZigbeeClusterLibrary::ClusterIdBinaryInput);
if (!binaryInputCluster) {
qCWarning(dcZigbeeDevelco()) << "Could not find BinaryInput cluster on" << thing << node << input4Endpoint;
} else {
if (binaryInputCluster->hasAttribute(ZigbeeClusterLibrary::ClusterIdBinaryInput)) {
thing->setStateValue(ioModuleInput4StateTypeId, binaryInputCluster->presentValue());
}
connect(binaryInputCluster, &ZigbeeClusterBinaryInput::presentValueChanged, thing, [thing](bool presentValue){
qCDebug(dcZigbeeDevelco()) << thing << "input 4 changed to" << presentValue;
thing->setStateValue(ioModuleInput4StateTypeId, presentValue);
});
}
}
}
info->finish(Thing::ThingErrorNoError);
}
void IntegrationPluginZigbeeDevelco::postSetupThing(Thing *thing)
{
if (thing->thingClassId() == ioModuleThingClassId) {
if (m_thingNodes.value(thing)->reachable()) {
readIoModuleOutputPowerStates(thing);
readIoModuleInputPowerStates(thing);
}
}
}
void IntegrationPluginZigbeeDevelco::executeAction(ThingActionInfo *info)
{
if (!hardwareManager()->zigbeeResource()->available()) {
info->finish(Thing::ThingErrorHardwareNotAvailable);
return;
}
// Get the node
Thing *thing = info->thing();
ZigbeeNode *node = m_thingNodes.value(thing);
if (!node->reachable()) {
info->finish(Thing::ThingErrorHardwareNotAvailable);
return;
}
if (thing->thingClassId() == ioModuleThingClassId) {
// Identify
if (info->action().actionTypeId() == ioModuleAlertActionTypeId) {
ZigbeeNodeEndpoint *primaryEndpoint = node->getEndpoint(IO_MODULE_EP_INPUT1);
if (!primaryEndpoint) {
qCWarning(dcZigbeeDevelco()) << "Could not find endpoint for execute action on" << thing << node;
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
ZigbeeClusterIdentify *identifyCluster = primaryEndpoint->inputCluster<ZigbeeClusterIdentify>(ZigbeeClusterLibrary::ClusterIdIdentify);
if (!identifyCluster) {
qCWarning(dcZigbeeDevelco()) << "Could not find identify cluster for" << thing << "in" << node;
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
// Send the command trough the network
ZigbeeClusterReply *reply = identifyCluster->identify(2);
connect(reply, &ZigbeeClusterReply::finished, this, [reply, info](){
// Note: reply will be deleted automatically
if (reply->error() != ZigbeeClusterReply::ErrorNoError) {
info->finish(Thing::ThingErrorHardwareFailure);
} else {
info->finish(Thing::ThingErrorNoError);
}
});
return;
}
// Output 1
if (info->action().actionTypeId() == ioModuleOutput1ActionTypeId) {
bool power = info->action().paramValue(ioModuleOutput1ActionOutput1ParamTypeId).toBool();
qCDebug(dcZigbeeDevelco()) << "Set output 1 power of" << thing << "to" << power;
ZigbeeNodeEndpoint *output1Endpoint = node->getEndpoint(IO_MODULE_EP_OUTPUT1);
if (!output1Endpoint) {
qCWarning(dcZigbeeDevelco()) << "Could not find endpoint for output 1 on" << thing << node;
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
ZigbeeClusterOnOff *onOffCluster = output1Endpoint->inputCluster<ZigbeeClusterOnOff>(ZigbeeClusterLibrary::ClusterIdOnOff);
if (!onOffCluster) {
qCWarning(dcZigbeeDevelco()) << "Could not find On/Off cluster on" << thing << node << output1Endpoint;
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
ZigbeeClusterReply *reply = (power ? onOffCluster->commandOn() : onOffCluster->commandOff());
connect(reply, &ZigbeeClusterReply::finished, info, [=](){
// Note: reply will be deleted automatically
if (reply->error() != ZigbeeClusterReply::ErrorNoError) {
qCWarning(dcZigbeeDevelco()) << "Failed to set power for output 1 on" << thing << reply->error();
info->finish(Thing::ThingErrorHardwareFailure);
} else {
info->finish(Thing::ThingErrorNoError);
qCDebug(dcZigbeeDevelco()) << "Set power on output 1 finished successfully for" << thing;
thing->setStateValue(ioModuleOutput1StateTypeId, power);
}
});
return;
}
// Output 2
if (info->action().actionTypeId() == ioModuleOutput2ActionTypeId) {
bool power = info->action().paramValue(ioModuleOutput2ActionOutput2ParamTypeId).toBool();
qCDebug(dcZigbeeDevelco()) << "Set output 2 power of" << thing << "to" << power;
ZigbeeNodeEndpoint *output2Endpoint = node->getEndpoint(IO_MODULE_EP_OUTPUT2);
if (!output2Endpoint) {
qCWarning(dcZigbeeDevelco()) << "Could not find endpoint for output 2 on" << thing << node;
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
ZigbeeClusterOnOff *onOffCluster = output2Endpoint->inputCluster<ZigbeeClusterOnOff>(ZigbeeClusterLibrary::ClusterIdOnOff);
if (!onOffCluster) {
qCWarning(dcZigbeeDevelco()) << "Could not find On/Off cluster on" << thing << node << output2Endpoint;
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
ZigbeeClusterReply *reply = (power ? onOffCluster->commandOn() : onOffCluster->commandOff());
connect(reply, &ZigbeeClusterReply::finished, info, [=](){
// Note: reply will be deleted automatically
if (reply->error() != ZigbeeClusterReply::ErrorNoError) {
qCWarning(dcZigbeeDevelco()) << "Failed to set power for output 2 on" << thing << reply->error();
info->finish(Thing::ThingErrorHardwareFailure);
} else {
info->finish(Thing::ThingErrorNoError);
qCDebug(dcZigbeeDevelco()) << "Set power on output 2 finished successfully for" << thing;
thing->setStateValue(ioModuleOutput2StateTypeId, power);
}
});
return;
}
// Impulse action
if (info->action().actionTypeId() == ioModuleImpulseOutput1ActionTypeId || info->action().actionTypeId() == ioModuleImpulseOutput2ActionTypeId) {
// Uint for time is 1/10 s
uint impulseDuration = thing->settings().paramValue(ioModuleSettingsImpulseDurationParamTypeId).toUInt();
quint16 impulseDurationScaled = static_cast<quint16>(qRound(impulseDuration / 100.0));
ZigbeeNodeEndpoint *endpoint = nullptr;
if (info->action().actionTypeId() == ioModuleImpulseOutput1ActionTypeId) {
endpoint = node->getEndpoint(IO_MODULE_EP_OUTPUT1);
qCDebug(dcZigbeeDevelco()) << "Execute output 1 impulse with" << impulseDurationScaled * 100 << "ms";
} else if (info->action().actionTypeId() == ioModuleImpulseOutput2ActionTypeId) {
endpoint = node->getEndpoint(IO_MODULE_EP_OUTPUT2);
qCDebug(dcZigbeeDevelco()) << "Execute output 2 impulse with" << impulseDurationScaled * 100 << "ms";
}
if (!endpoint) {
qCWarning(dcZigbeeDevelco()) << "Could not find endpoint for impulse action on" << thing << node;
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
ZigbeeClusterOnOff *onOffCluster = endpoint->inputCluster<ZigbeeClusterOnOff>(ZigbeeClusterLibrary::ClusterIdOnOff);
if (!onOffCluster) {
qCWarning(dcZigbeeDevelco()) << "Could not find On/Off cluster on" << thing << node << endpoint;
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
ZigbeeClusterReply *reply = onOffCluster->commandOnWithTimedOff(false, impulseDurationScaled, 0);
connect(reply, &ZigbeeClusterReply::finished, info, [=](){
// Note: reply will be deleted automatically
if (reply->error() != ZigbeeClusterReply::ErrorNoError) {
qCWarning(dcZigbeeDevelco()) << "Failed to set on with timed off on" << thing << endpoint << reply->error();
info->finish(Thing::ThingErrorHardwareFailure);
} else {
info->finish(Thing::ThingErrorNoError);
qCDebug(dcZigbeeDevelco()) << "Set on with timed off on finished successfully for" << thing << endpoint;
}
});
return;
}
}
info->finish(Thing::ThingErrorUnsupportedFeature);
}
void IntegrationPluginZigbeeDevelco::thingRemoved(Thing *thing)
{
ZigbeeNode *node = m_thingNodes.take(thing);
if (node) {
QUuid networkUuid = thing->paramValue(m_networkUuidParamTypeIds.value(thing->thingClassId())).toUuid();
hardwareManager()->zigbeeResource()->removeNodeFromNetwork(networkUuid, node);
}
}
void IntegrationPluginZigbeeDevelco::createThing(const ThingClassId &thingClassId, const QUuid &networkUuid, ZigbeeNode *node)
{
ThingDescriptor descriptor(thingClassId);
QString deviceClassName = supportedThings().findById(thingClassId).displayName();
descriptor.setTitle(QString("%1 (%2 - %3)").arg(deviceClassName, node->manufacturerName(), node->modelName()));
ParamList params;
params.append(Param(m_networkUuidParamTypeIds[thingClassId], networkUuid.toString()));
params.append(Param(m_ieeeAddressParamTypeIds[thingClassId], node->extendedAddress().toString()));
descriptor.setParams(params);
emit autoThingsAppeared({descriptor});
}
QString IntegrationPluginZigbeeDevelco::parseDevelcoVersionString(ZigbeeNodeEndpoint *endpoint)
{
QString versionString;
ZigbeeCluster *basicCluster = endpoint->getInputCluster(ZigbeeClusterLibrary::ClusterIdBasic);
if (!basicCluster) {
qCWarning(dcZigbeeDevelco()) << "Could not find basic cluster on" << endpoint << "for version parsing";
return versionString;
}
if (!basicCluster->hasAttribute(DEVELCO_ATTRIBUTE_SW_VERSION)) {
qCWarning(dcZigbeeDevelco()) << "Could not find manufacturer specific develco software version attribute in basic cluster on" << endpoint;
return versionString;
}
ZigbeeClusterAttribute versionAttribute = basicCluster->attribute(DEVELCO_ATTRIBUTE_SW_VERSION);
// 1 Byte octet string length, 3 byte version infromation
if (versionAttribute.dataType().data().length() < 4 || versionAttribute.dataType().data().at(0) != 3) {
qCWarning(dcZigbeeDevelco()) << "Failed to parse version string from manufacturer specific develco software version attribute" << versionAttribute;
return versionString;
}
int majorVersion = static_cast<int>(versionAttribute.dataType().data().at(1));
int minorVersion = static_cast<int>(versionAttribute.dataType().data().at(2));
int patchVersion = static_cast<int>(versionAttribute.dataType().data().at(3));
versionString = QString("%1.%2.%3").arg(majorVersion).arg(minorVersion).arg(patchVersion);
//qCDebug(dcZigbeeDevelco()) << versionAttribute << ZigbeeUtils::convertByteArrayToHexString(versionAttribute.dataType().data()) << versionString;
return versionString;
}
void IntegrationPluginZigbeeDevelco::initIoModule(ZigbeeNode *node)
{
qCDebug(dcZigbeeDevelco()) << "Start initializing IO Module" << node;
readDevelcoFirmwareVersion(node, node->getEndpoint(IO_MODULE_EP_INPUT1));
// Binding and reporting outputs
configureOnOffPowerReporting(node, node->getEndpoint(IO_MODULE_EP_OUTPUT1));
configureOnOffPowerReporting(node, node->getEndpoint(IO_MODULE_EP_OUTPUT2));
// Binding and reporting inputs
configureBinaryInputReporting(node, node->getEndpoint(IO_MODULE_EP_INPUT1));
configureBinaryInputReporting(node, node->getEndpoint(IO_MODULE_EP_INPUT2));
configureBinaryInputReporting(node, node->getEndpoint(IO_MODULE_EP_INPUT3));
configureBinaryInputReporting(node, node->getEndpoint(IO_MODULE_EP_INPUT4));
}
void IntegrationPluginZigbeeDevelco::configureOnOffPowerReporting(ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint)
{
qCDebug(dcZigbeeDevelco()) << "Bind on/off cluster to coordinator IEEE address" << node << endpoint;
ZigbeeDeviceObjectReply * zdoReply = node->deviceObject()->requestBindIeeeAddress(endpoint->endpointId(), ZigbeeClusterLibrary::ClusterIdOnOff, hardwareManager()->zigbeeResource()->coordinatorAddress(node->networkUuid()), 0x01);
connect(zdoReply, &ZigbeeDeviceObjectReply::finished, node, [=](){
if (zdoReply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
qCWarning(dcZigbeeDevelco()) << "Failed to bind on/off cluster to coordinator" << zdoReply->error();
} else {
qCDebug(dcZigbeeDevelco()) << "Bind on/off cluster to coordinator finished successfully";
}
// Configure attribute reporting for lock state
ZigbeeClusterLibrary::AttributeReportingConfiguration reportingConfig;
reportingConfig.attributeId = ZigbeeClusterOnOff::AttributeOnOff;
reportingConfig.minReportingInterval = 0;
reportingConfig.maxReportingInterval = 600;
reportingConfig.dataType = Zigbee::Bool;
qCDebug(dcZigbeeDevelco()) << "Configure attribute reporting for on/off cluster" << node << endpoint;
ZigbeeClusterReply *reportingReply = endpoint->getInputCluster(ZigbeeClusterLibrary::ClusterIdOnOff)->configureReporting({reportingConfig});
connect(reportingReply, &ZigbeeClusterReply::finished, this, [=](){
if (reportingReply->error() != ZigbeeClusterReply::ErrorNoError) {
qCWarning(dcZigbeeDevelco()) << "Failed configure attribute reporting on on/off cluster" << reportingReply->error();
} else {
qCDebug(dcZigbeeDevelco()) << "Attribute reporting configuration finished for on/off cluster" << ZigbeeClusterLibrary::parseAttributeReportingStatusRecords(reportingReply->responseFrame().payload);
}
});
});
}
void IntegrationPluginZigbeeDevelco::configureBinaryInputReporting(ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint)
{
qCDebug(dcZigbeeDevelco()) << "Bind binary input cluster to coordinator IEEE address" << node << endpoint;
ZigbeeDeviceObjectReply * zdoReply = node->deviceObject()->requestBindIeeeAddress(endpoint->endpointId(), ZigbeeClusterLibrary::ClusterIdBinaryInput, hardwareManager()->zigbeeResource()->coordinatorAddress(node->networkUuid()), 0x01);
connect(zdoReply, &ZigbeeDeviceObjectReply::finished, node, [=](){
if (zdoReply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
qCWarning(dcZigbeeDevelco()) << "Failed to bind binary input cluster to coordinator" << zdoReply->error();
} else {
qCDebug(dcZigbeeDevelco()) << "Bind binary input cluster to coordinator finished successfully";
}
// Configure attribute reporting for lock state
ZigbeeClusterLibrary::AttributeReportingConfiguration reportingConfig;
reportingConfig.attributeId = ZigbeeClusterBinaryInput::AttributePresentValue;
reportingConfig.minReportingInterval = 0;
reportingConfig.maxReportingInterval = 600;
reportingConfig.dataType = Zigbee::Bool;
qCDebug(dcZigbeeDevelco()) << "Configure attribute reporting for binary input cluster" << node << endpoint;
ZigbeeClusterReply *reportingReply = endpoint->getInputCluster(ZigbeeClusterLibrary::ClusterIdBinaryInput)->configureReporting({reportingConfig});
connect(reportingReply, &ZigbeeClusterReply::finished, this, [=](){
if (reportingReply->error() != ZigbeeClusterReply::ErrorNoError) {
qCWarning(dcZigbeeDevelco()) << "Failed configure attribute reporting on binary input cluster" << reportingReply->error();
} else {
qCDebug(dcZigbeeDevelco()) << "Attribute reporting configuration finished for on binary input cluster" << ZigbeeClusterLibrary::parseAttributeReportingStatusRecords(reportingReply->responseFrame().payload);
}
});
});
}
void IntegrationPluginZigbeeDevelco::readDevelcoFirmwareVersion(ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint)
{
// Read manufacturer specific basic cluster attribute 0x8000
ZigbeeClusterBasic *basicCluster = endpoint->inputCluster<ZigbeeClusterBasic>(ZigbeeClusterLibrary::ClusterIdBasic);
if (!basicCluster) {
qCWarning(dcZigbeeDevelco()) << "Could not find basic cluster for manufacturer specific attribute reading on" << node << endpoint;
return;
}
// We have to read the color capabilities
ZigbeeClusterReply *reply = basicCluster->readAttributes({DEVELCO_ATTRIBUTE_SW_VERSION}, Zigbee::Develco);
connect(reply, &ZigbeeClusterReply::finished, node, [=](){
if (reply->error() != ZigbeeClusterReply::ErrorNoError) {
qCWarning(dcZigbeeDevelco()) << "Failed to read manufacturer specific version attribute on" << node << endpoint << basicCluster;
return;
}
qCDebug(dcZigbeeDevelco()) << "Reading develco manufacturer specific version attributes finished successfully";
});
}
void IntegrationPluginZigbeeDevelco::readOnOffPowerAttribute(ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint)
{
qCDebug(dcZigbeeDevelco()) << "Reading power states of" << node << "on" << endpoint;
ZigbeeClusterOnOff *onOffCluster = endpoint->inputCluster<ZigbeeClusterOnOff>(ZigbeeClusterLibrary::ClusterIdOnOff);
if (!onOffCluster) {
qCWarning(dcZigbeeDevelco()) << "Could not find On/Off cluster on" << node << endpoint;
} else {
ZigbeeClusterReply *reply = onOffCluster->readAttributes({ZigbeeClusterOnOff::AttributeOnOff});
connect(reply, &ZigbeeClusterReply::finished, node, [=](){
if (reply->error() != ZigbeeClusterReply::ErrorNoError) {
qCWarning(dcZigbeeDevelco()) << "Failed to read On/Off power attribute from" << node << endpoint << onOffCluster;
}
// Will be updated trough the attribute changed signal
});
}
}
void IntegrationPluginZigbeeDevelco::readBinaryInputPresentValueAttribute(ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint)
{
ZigbeeClusterBinaryInput *binaryInputCluster = endpoint->inputCluster<ZigbeeClusterBinaryInput>(ZigbeeClusterLibrary::ClusterIdBinaryInput);
if (!binaryInputCluster) {
qCWarning(dcZigbeeDevelco()) << "Could not find BinaryInput cluster on" << node << endpoint;
} else {
ZigbeeClusterReply *reply = binaryInputCluster->readAttributes({ZigbeeClusterBinaryInput::AttributePresentValue});
connect(reply, &ZigbeeClusterReply::finished, node, [=](){
if (reply->error() != ZigbeeClusterReply::ErrorNoError) {
qCWarning(dcZigbeeDevelco()) << "Failed to read binary input value attribute from" << node << endpoint << binaryInputCluster;
}
// Will be updated trough the attribute changed signal
});
}
}
void IntegrationPluginZigbeeDevelco::readIoModuleOutputPowerStates(Thing *thing)
{
ZigbeeNode *node = m_thingNodes.value(thing);
if (!node) {
qCWarning(dcZigbeeDevelco()) << "Could not find zigbee node for" << thing;
return;
}
qCDebug(dcZigbeeDevelco()) << "Start reading power states of" << thing << node;
// Read output 1 power state
ZigbeeNodeEndpoint *output1Endpoint = node->getEndpoint(IO_MODULE_EP_OUTPUT1);
if (!output1Endpoint) {
qCWarning(dcZigbeeDevelco()) << "Could not find endpoint for output 1 on" << thing << node;
} else {
readOnOffPowerAttribute(node, output1Endpoint);
}
// Read output 2 power state
ZigbeeNodeEndpoint *output2Endpoint = node->getEndpoint(IO_MODULE_EP_OUTPUT2);
if (!output2Endpoint) {
qCWarning(dcZigbeeDevelco()) << "Could not find endpoint for output 2 on" << thing << node;
} else {
readOnOffPowerAttribute(node, output2Endpoint);
}
}
void IntegrationPluginZigbeeDevelco::readIoModuleInputPowerStates(Thing *thing)
{
ZigbeeNode *node = m_thingNodes.value(thing);
if (!node) {
qCWarning(dcZigbeeDevelco()) << "Could not find zigbee node for" << thing;
return;
}
// Read input 1 state
ZigbeeNodeEndpoint *input1Endpoint = node->getEndpoint(IO_MODULE_EP_INPUT1);
if (!input1Endpoint) {
qCWarning(dcZigbeeDevelco()) << "Could not find endpoint for input 1 on" << thing << node;
} else {
readBinaryInputPresentValueAttribute(node, input1Endpoint);
}
// Read input 2 state
ZigbeeNodeEndpoint *input2Endpoint = node->getEndpoint(IO_MODULE_EP_INPUT2);
if (!input2Endpoint) {
qCWarning(dcZigbeeDevelco()) << "Could not find endpoint for input 2 on" << thing << node;
} else {
readBinaryInputPresentValueAttribute(node, input2Endpoint);
}
// Read input 3 state
ZigbeeNodeEndpoint *input3Endpoint = node->getEndpoint(IO_MODULE_EP_INPUT3);
if (!input3Endpoint) {
qCWarning(dcZigbeeDevelco()) << "Could not find endpoint for input 3 on" << thing << node;
} else {
readBinaryInputPresentValueAttribute(node, input3Endpoint);
}
// Read input 4 state
ZigbeeNodeEndpoint *input4Endpoint = node->getEndpoint(IO_MODULE_EP_INPUT4);
if (!input4Endpoint) {
qCWarning(dcZigbeeDevelco()) << "Could not find endpoint for input 4 on" << thing << node;
} else {
readBinaryInputPresentValueAttribute(node, input4Endpoint);
}
}

View File

@ -0,0 +1,123 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2021, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; version 3. This project is distributed in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef INTEGRATIONPLUGINZIGBEEDEVELCO_H
#define INTEGRATIONPLUGINZIGBEEDEVELCO_H
#include "integrations/integrationplugin.h"
#include "hardware/zigbee/zigbeehandler.h"
#include "plugintimer.h"
#include <QTimer>
#include <zigbeereply.h>
/* IO Module
*
* https://www.develcoproducts.com/media/1967/iomzb-110-technical-manual-io-module.pdf
*
* Profile 0xC0C9 (Develco Products private profile)
* Endpoints:
* - 0x70 Simple sensor: input 1
* - 0x71 Simple sensor: input 2
* - 0x72 Simple sensor: input 3
* - 0x74 Simple sensor: input 4
* - 0x75 On/Off Output : relay 1
* - 0x76 On/Off Output : relay 2
*/
#define IO_MODULE_EP_INPUT1 0x70
#define IO_MODULE_EP_INPUT2 0x71
#define IO_MODULE_EP_INPUT3 0x72
#define IO_MODULE_EP_INPUT4 0x73
#define IO_MODULE_EP_OUTPUT1 0x74
#define IO_MODULE_EP_OUTPUT2 0x75
/* Develco manufacturer specific Basic cluster attributes
* 0x8000 Primary SW version
* 0x8010 Primary Bootloader SW version
* 0x8020 Primary HW version
* 0x8030 Primary HW name
* 0x8050 Primary SW version 3rd party
*/
#define DEVELCO_ATTRIBUTE_SW_VERSION 0x8000
#define DEVELCO_ATTRIBUTE_BOOTLOADER_VERSION 0x8010
#define DEVELCO_ATTRIBUTE_HARDWARE_VERSION 0x8020
#define DEVELCO_ATTRIBUTE_HARDWARE_NAME 0x8030
#define DEVELCO_ATTRIBUTE_3RD_PARTY_SW_VERSION 0x8050
class IntegrationPluginZigbeeDevelco: public IntegrationPlugin, public ZigbeeHandler
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginzigbeedevelco.json")
Q_INTERFACES(IntegrationPlugin)
public:
explicit IntegrationPluginZigbeeDevelco();
QString name() const override;
bool handleNode(ZigbeeNode *node, const QUuid &networkUuid) override;
void handleRemoveNode(ZigbeeNode *node, const QUuid &networkUuid) override;
void init() override;
void setupThing(ThingSetupInfo *info) override;
void postSetupThing(Thing *thing) override;
void executeAction(ThingActionInfo *info) override;
void thingRemoved(Thing *thing) override;
private:
QHash<Thing*, ZigbeeNode*> m_thingNodes;
QHash<ThingClassId, ParamTypeId> m_ieeeAddressParamTypeIds;
QHash<ThingClassId, ParamTypeId> m_networkUuidParamTypeIds;
QHash<ThingClassId, StateTypeId> m_connectedStateTypeIds;
QHash<ThingClassId, StateTypeId> m_signalStrengthStateTypeIds;
// Get the endpoint for the given thing
void createThing(const ThingClassId &thingClassId, const QUuid &networkUuid, ZigbeeNode *node);
QString parseDevelcoVersionString(ZigbeeNodeEndpoint *endpoint);
void initIoModule(ZigbeeNode *node);
void configureOnOffPowerReporting(ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint);
void configureBinaryInputReporting(ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint);
void readDevelcoFirmwareVersion(ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint);
void readOnOffPowerAttribute(ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint);
void readBinaryInputPresentValueAttribute(ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint);
void readIoModuleOutputPowerStates(Thing *thing);
void readIoModuleInputPowerStates(Thing *thing);
};
#endif // INTEGRATIONPLUGINZIGBEEDEVELCO_H

View File

@ -0,0 +1,154 @@
{
"name": "ZigbeeDevelco",
"displayName": "Zigbee Develco",
"id": "1b9e976d-e842-40e1-9fad-87d71a69c721",
"vendors": [
{
"name": "develco",
"displayName": "Develco",
"id": "e4b36f3e-ccdc-4a88-8968-39025c3ec742",
"thingClasses": [
{
"id": "3fb419ef-795d-4f4d-b801-e7eaff16cdb0",
"name": "ioModule",
"displayName": "IO Module",
"createMethods": ["auto"],
"interfaces": ["wirelessconnectable", "alert"],
"paramTypes": [
{
"id": "d9a3afa7-c460-43e7-bc84-c8b5ff1adf44",
"name": "ieeeAddress",
"displayName": "IEEE adress",
"type": "QString",
"defaultValue": "00:00:00:00:00:00:00:00"
},
{
"id": "f4c83d2b-06e1-4206-98b7-e3ace79ff447",
"name": "networkUuid",
"displayName": "Zigbee network UUID",
"type": "QString",
"defaultValue": ""
}
],
"settingsTypes": [
{
"id": "c2806b97-bf94-4ad2-ae22-5b5d7d1eaf5a",
"name": "impulseDuration",
"displayName": "Impulse duration",
"type": "uint",
"unit": "MilliSeconds",
"defaultValue": 100,
"minValue": 100
}
],
"stateTypes": [
{
"id": "16d5ebb7-21d1-4294-98a6-ca06eea8e3a3",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"type": "bool",
"cached": false,
"defaultValue": false
},
{
"id": "0e09e6a6-8b3f-4b63-acb1-ac04ab31957a",
"name": "signalStrength",
"displayName": "Signal strength",
"displayNameEvent": "Signal strength changed",
"defaultValue": 0,
"maxValue": 100,
"minValue": 0,
"type": "uint",
"unit": "Percentage"
},
{
"id": "f28c9a61-b8ab-419c-bd85-58692df26ac7",
"name": "version",
"displayName": "Version",
"displayNameEvent": "Version changed",
"type": "QString",
"cached": true,
"defaultValue": ""
},
{
"id": "aaeda2c6-439a-452a-b829-45d6249bdee6",
"name": "output1",
"displayName": "Output 1",
"displayNameEvent": "Output 1 changed",
"displayNameAction": "Set output 1",
"type": "bool",
"writable": true,
"defaultValue": false,
"ioType": "digitalOutput"
},
{
"id": "105cf314-35b5-4a8b-8e6d-d011009f97ff",
"name": "output2",
"displayName": "Output 2",
"displayNameEvent": "Output 2 changed",
"displayNameAction": "Set output 2",
"type": "bool",
"writable": true,
"defaultValue": false,
"ioType": "digitalOutput"
},
{
"id": "bc23c7e8-f4ad-47c4-b938-f9af2dbd3393",
"name": "input1",
"displayName": "Input 1",
"displayNameEvent": "Input 1 changed",
"type": "bool",
"defaultValue": false,
"ioType": "digitalInput"
},
{
"id": "065b0dc0-6d31-40ec-b356-02fea57e2fe1",
"name": "input2",
"displayName": "Input 2",
"displayNameEvent": "Input 2 changed",
"type": "bool",
"defaultValue": false,
"ioType": "digitalInput"
},
{
"id": "8f2b052a-30b7-49aa-a8d4-503cb0b9b66b",
"name": "input3",
"displayName": "Input 3",
"displayNameEvent": "Input 3 changed",
"type": "bool",
"defaultValue": false,
"ioType": "digitalInput"
},
{
"id": "caef986c-da13-4ef3-ab81-316244c7be1e",
"name": "input4",
"displayName": "Input 4",
"displayNameEvent": "Input 4 changed",
"type": "bool",
"defaultValue": false,
"ioType": "digitalInput"
}
],
"actionTypes": [
{
"id": "62c5562a-8bdf-49b4-8e1d-f27442b2b360",
"name": "alert",
"displayName": "Identify"
},
{
"id": "45ec5c65-0719-4148-82ea-3e69b34be939",
"name": "impulseOutput1",
"displayName": "Impulse output 1"
},
{
"id": "d780946c-4ddf-4b59-a669-dbf6ecfda5d6",
"name": "impulseOutput2",
"displayName": "Impulse output 2"
}
]
}
]
}
]
}

12
zigbeedevelco/meta.json Normal file
View File

@ -0,0 +1,12 @@
{
"title": "ZigBee Develco",
"tagline": "Connect and control native ZigBee devices from Develco.",
"icon": "develcologo.png",
"stability": "consumer",
"offline": true,
"technologies": [
"zigbee"
],
"categories": [
]
}

View File

@ -0,0 +1,214 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<name>ZigbeeDevelco</name>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="65"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="68"/>
<source>Connected</source>
<extracomment>The name of the ParamType (ThingClass: ioModule, EventType: connected, ID: {16d5ebb7-21d1-4294-98a6-ca06eea8e3a3})
----------
The name of the StateType ({16d5ebb7-21d1-4294-98a6-ca06eea8e3a3}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="71"/>
<source>Connected changed</source>
<extracomment>The name of the EventType ({16d5ebb7-21d1-4294-98a6-ca06eea8e3a3}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="74"/>
<source>Develco</source>
<extracomment>The name of the vendor ({e4b36f3e-ccdc-4a88-8968-39025c3ec742})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="77"/>
<source>IEEE adress</source>
<extracomment>The name of the ParamType (ThingClass: ioModule, Type: thing, ID: {d9a3afa7-c460-43e7-bc84-c8b5ff1adf44})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="80"/>
<source>IO Module</source>
<extracomment>The name of the ThingClass ({3fb419ef-795d-4f4d-b801-e7eaff16cdb0})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="83"/>
<source>Identify</source>
<extracomment>The name of the ActionType ({62c5562a-8bdf-49b4-8e1d-f27442b2b360}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="86"/>
<source>Impulse duration</source>
<extracomment>The name of the ParamType (ThingClass: ioModule, Type: settings, ID: {c2806b97-bf94-4ad2-ae22-5b5d7d1eaf5a})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="89"/>
<source>Impulse output 1</source>
<extracomment>The name of the ActionType ({45ec5c65-0719-4148-82ea-3e69b34be939}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="92"/>
<source>Impulse output 2</source>
<extracomment>The name of the ActionType ({d780946c-4ddf-4b59-a669-dbf6ecfda5d6}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="95"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="98"/>
<source>Input 1</source>
<extracomment>The name of the ParamType (ThingClass: ioModule, EventType: input1, ID: {bc23c7e8-f4ad-47c4-b938-f9af2dbd3393})
----------
The name of the StateType ({bc23c7e8-f4ad-47c4-b938-f9af2dbd3393}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="101"/>
<source>Input 1 changed</source>
<extracomment>The name of the EventType ({bc23c7e8-f4ad-47c4-b938-f9af2dbd3393}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="104"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="107"/>
<source>Input 2</source>
<extracomment>The name of the ParamType (ThingClass: ioModule, EventType: input2, ID: {065b0dc0-6d31-40ec-b356-02fea57e2fe1})
----------
The name of the StateType ({065b0dc0-6d31-40ec-b356-02fea57e2fe1}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="110"/>
<source>Input 2 changed</source>
<extracomment>The name of the EventType ({065b0dc0-6d31-40ec-b356-02fea57e2fe1}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="113"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="116"/>
<source>Input 3</source>
<extracomment>The name of the ParamType (ThingClass: ioModule, EventType: input3, ID: {8f2b052a-30b7-49aa-a8d4-503cb0b9b66b})
----------
The name of the StateType ({8f2b052a-30b7-49aa-a8d4-503cb0b9b66b}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="119"/>
<source>Input 3 changed</source>
<extracomment>The name of the EventType ({8f2b052a-30b7-49aa-a8d4-503cb0b9b66b}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="122"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="125"/>
<source>Input 4</source>
<extracomment>The name of the ParamType (ThingClass: ioModule, EventType: input4, ID: {caef986c-da13-4ef3-ab81-316244c7be1e})
----------
The name of the StateType ({caef986c-da13-4ef3-ab81-316244c7be1e}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="128"/>
<source>Input 4 changed</source>
<extracomment>The name of the EventType ({caef986c-da13-4ef3-ab81-316244c7be1e}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="131"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="134"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="137"/>
<source>Output 1</source>
<extracomment>The name of the ParamType (ThingClass: ioModule, ActionType: output1, ID: {aaeda2c6-439a-452a-b829-45d6249bdee6})
----------
The name of the ParamType (ThingClass: ioModule, EventType: output1, ID: {aaeda2c6-439a-452a-b829-45d6249bdee6})
----------
The name of the StateType ({aaeda2c6-439a-452a-b829-45d6249bdee6}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="140"/>
<source>Output 1 changed</source>
<extracomment>The name of the EventType ({aaeda2c6-439a-452a-b829-45d6249bdee6}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="143"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="146"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="149"/>
<source>Output 2</source>
<extracomment>The name of the ParamType (ThingClass: ioModule, ActionType: output2, ID: {105cf314-35b5-4a8b-8e6d-d011009f97ff})
----------
The name of the ParamType (ThingClass: ioModule, EventType: output2, ID: {105cf314-35b5-4a8b-8e6d-d011009f97ff})
----------
The name of the StateType ({105cf314-35b5-4a8b-8e6d-d011009f97ff}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="152"/>
<source>Output 2 changed</source>
<extracomment>The name of the EventType ({105cf314-35b5-4a8b-8e6d-d011009f97ff}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="155"/>
<source>Set output 1</source>
<extracomment>The name of the ActionType ({aaeda2c6-439a-452a-b829-45d6249bdee6}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="158"/>
<source>Set output 2</source>
<extracomment>The name of the ActionType ({105cf314-35b5-4a8b-8e6d-d011009f97ff}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="161"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="164"/>
<source>Signal strength</source>
<extracomment>The name of the ParamType (ThingClass: ioModule, EventType: signalStrength, ID: {0e09e6a6-8b3f-4b63-acb1-ac04ab31957a})
----------
The name of the StateType ({0e09e6a6-8b3f-4b63-acb1-ac04ab31957a}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="167"/>
<source>Signal strength changed</source>
<extracomment>The name of the EventType ({0e09e6a6-8b3f-4b63-acb1-ac04ab31957a}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="170"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="173"/>
<source>Version</source>
<extracomment>The name of the ParamType (ThingClass: ioModule, EventType: version, ID: {f28c9a61-b8ab-419c-bd85-58692df26ac7})
----------
The name of the StateType ({f28c9a61-b8ab-419c-bd85-58692df26ac7}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="176"/>
<source>Version changed</source>
<extracomment>The name of the EventType ({f28c9a61-b8ab-419c-bd85-58692df26ac7}) of ThingClass ioModule</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="179"/>
<source>Zigbee Develco</source>
<extracomment>The name of the plugin ZigbeeDevelco ({1b9e976d-e842-40e1-9fad-87d71a69c721})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/zigbeedevelco/plugininfo.h" line="182"/>
<source>Zigbee network UUID</source>
<extracomment>The name of the ParamType (ThingClass: ioModule, Type: thing, ID: {f4c83d2b-06e1-4206-98b7-e3ace79ff447})</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -0,0 +1,12 @@
include(../plugins.pri)
PKGCONFIG += nymea-zigbee
SOURCES += \
integrationpluginzigbeedevelco.cpp
HEADERS += \
integrationpluginzigbeedevelco.h