Add lumi relay and add ioType to lumi things

This commit is contained in:
Simon Stürz 2020-11-19 08:46:26 +01:00
parent ef57c2d0b1
commit a58ee272e1
2 changed files with 202 additions and 6 deletions

View File

@ -238,7 +238,8 @@
"displayName": "Closed",
"displayNameEvent": "Closed changed",
"type": "bool",
"defaultValue": true
"defaultValue": true,
"ioType": "digitalInput"
}
],
"actionTypes": [
@ -387,7 +388,8 @@
"displayName": "Present",
"displayNameEvent": "Present changed",
"type": "bool",
"defaultValue": true
"defaultValue": true,
"ioType": "digitalInput"
},
{
"id": "021ce190-a775-40e0-b19b-c6307c73e343",
@ -474,7 +476,8 @@
"displayName": "Water detected",
"displayNameEvent": "Water detected changed",
"type": "bool",
"defaultValue": true
"defaultValue": true,
"ioType": "digitalInput"
},
{
"id": "72aa617c-88cc-4992-a1a2-400b5e19106e",
@ -618,7 +621,8 @@
"displayNameAction": "Set power",
"type": "bool",
"defaultValue": false,
"writable": true
"writable": true,
"ioType": "digitalOutput"
}
],
"actionTypes": [
@ -630,6 +634,89 @@
],
"eventTypes": [
]
},
{
"name": "lumiRelay",
"displayName": "Relay",
"id": "8e381cb1-2caa-4261-be77-e76a538bf67a",
"setupMethod": "JustAdd",
"createMethods": [ "Auto" ],
"interfaces": [ "wirelessconnectable" ],
"paramTypes": [
{
"id": "f4a51b83-9cfa-402f-9d2a-e42933e33660",
"name": "ieeeAddress",
"displayName": "IEEE adress",
"type": "QString",
"defaultValue": "00:00:00:00:00:00:00:00"
},
{
"id": "b5783bb8-ae1d-4e93-84f9-3f1e8c59b955",
"name": "networkUuid",
"displayName": "Zigbee network UUID",
"type": "QString",
"defaultValue": ""
}
],
"stateTypes": [
{
"id": "b12d1765-0b2e-4e95-b5ef-780d27fdda44",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"type": "bool",
"cached": false,
"defaultValue": false
},
{
"id": "bc22b220-003f-4f19-9aef-21c4049c5a0e",
"name": "signalStrength",
"displayName": "Signal strength",
"displayNameEvent": "Signal strength changed",
"defaultValue": 0,
"maxValue": 100,
"minValue": 0,
"type": "uint",
"unit": "Percentage"
},
{
"id": "ca1a8d08-4423-4401-bca7-d52b11e54ed9",
"name": "version",
"displayName": "Version",
"displayNameEvent": "Version changed",
"type": "QString",
"cached": true,
"defaultValue": ""
},
{
"id": "486e0df0-cbda-4b67-b844-6f70e5af6891",
"name": "relay1",
"displayName": "Relay 1",
"displayNameEvent": "Relay 1 changed",
"displayNameAction": "Set relay 1",
"type": "bool",
"writable": true,
"defaultValue": false,
"ioType": "digitalOutput"
},
{
"id": "2caa4f0f-661e-4b59-83e5-8417058e48fd",
"name": "relay2",
"displayName": "Relay 2",
"displayNameEvent": "Relay 2 changed",
"displayNameAction": "Set relay 2",
"type": "bool",
"writable": true,
"defaultValue": false,
"ioType": "digitalOutput"
}
],
"actionTypes": [
],
"eventTypes": [
]
}
]

View File

@ -47,6 +47,7 @@ IntegrationPluginZigbeeLumi::IntegrationPluginZigbeeLumi()
m_networkUuidParamTypeIds[lumiWeatherSensorThingClassId] = lumiWeatherSensorThingNetworkUuidParamTypeId;
m_networkUuidParamTypeIds[lumiVibrationSensorThingClassId] = lumiVibrationSensorThingNetworkUuidParamTypeId;
m_networkUuidParamTypeIds[lumiPowerSocketThingClassId] = lumiPowerSocketThingNetworkUuidParamTypeId;
m_networkUuidParamTypeIds[lumiRelayThingClassId] = lumiRelayThingNetworkUuidParamTypeId;
m_zigbeeAddressParamTypeIds[lumiHTSensorThingClassId] = lumiHTSensorThingIeeeAddressParamTypeId;
m_zigbeeAddressParamTypeIds[lumiButtonSensorThingClassId] = lumiButtonSensorThingIeeeAddressParamTypeId;
@ -56,6 +57,7 @@ IntegrationPluginZigbeeLumi::IntegrationPluginZigbeeLumi()
m_zigbeeAddressParamTypeIds[lumiWeatherSensorThingClassId] = lumiWeatherSensorThingIeeeAddressParamTypeId;
m_zigbeeAddressParamTypeIds[lumiVibrationSensorThingClassId] = lumiVibrationSensorThingIeeeAddressParamTypeId;
m_zigbeeAddressParamTypeIds[lumiPowerSocketThingClassId] = lumiPowerSocketThingIeeeAddressParamTypeId;
m_zigbeeAddressParamTypeIds[lumiRelayThingClassId] = lumiRelayThingIeeeAddressParamTypeId;
m_connectedStateTypeIds[lumiHTSensorThingClassId] = lumiHTSensorConnectedStateTypeId;
m_connectedStateTypeIds[lumiButtonSensorThingClassId] = lumiButtonSensorConnectedStateTypeId;
@ -65,6 +67,7 @@ IntegrationPluginZigbeeLumi::IntegrationPluginZigbeeLumi()
m_connectedStateTypeIds[lumiWeatherSensorThingClassId] = lumiWeatherSensorConnectedStateTypeId;
m_connectedStateTypeIds[lumiVibrationSensorThingClassId] = lumiVibrationSensorConnectedStateTypeId;
m_connectedStateTypeIds[lumiPowerSocketThingClassId] = lumiPowerSocketConnectedStateTypeId;
m_connectedStateTypeIds[lumiRelayThingClassId] = lumiRelayConnectedStateTypeId;
m_versionStateTypeIds[lumiHTSensorThingClassId] = lumiHTSensorVersionStateTypeId;
m_versionStateTypeIds[lumiButtonSensorThingClassId] = lumiButtonSensorVersionStateTypeId;
@ -74,6 +77,7 @@ IntegrationPluginZigbeeLumi::IntegrationPluginZigbeeLumi()
m_versionStateTypeIds[lumiWeatherSensorThingClassId] = lumiWeatherSensorVersionStateTypeId;
m_versionStateTypeIds[lumiVibrationSensorThingClassId] = lumiVibrationSensorVersionStateTypeId;
m_versionStateTypeIds[lumiPowerSocketThingClassId] = lumiPowerSocketVersionStateTypeId;
m_versionStateTypeIds[lumiRelayThingClassId] = lumiRelayVersionStateTypeId;
m_signalStrengthStateTypeIds[lumiHTSensorThingClassId] = lumiHTSensorSignalStrengthStateTypeId;
m_signalStrengthStateTypeIds[lumiButtonSensorThingClassId] = lumiButtonSensorSignalStrengthStateTypeId;
@ -83,6 +87,7 @@ IntegrationPluginZigbeeLumi::IntegrationPluginZigbeeLumi()
m_signalStrengthStateTypeIds[lumiWeatherSensorThingClassId] = lumiWeatherSensorSignalStrengthStateTypeId;
m_signalStrengthStateTypeIds[lumiVibrationSensorThingClassId] = lumiVibrationSensorSignalStrengthStateTypeId;
m_signalStrengthStateTypeIds[lumiPowerSocketThingClassId] = lumiPowerSocketSignalStrengthStateTypeId;
m_signalStrengthStateTypeIds[lumiRelayThingClassId] = lumiRelaySignalStrengthStateTypeId;
// Known model identifier
m_knownLumiDevices.insert("lumi.sensor_ht", lumiHTSensorThingClassId);
@ -93,6 +98,7 @@ IntegrationPluginZigbeeLumi::IntegrationPluginZigbeeLumi()
m_knownLumiDevices.insert("lumi.weather", lumiWeatherSensorThingClassId);
m_knownLumiDevices.insert("lumi.vibration", lumiVibrationSensorThingClassId);
m_knownLumiDevices.insert("lumi.plug", lumiPowerSocketThingClassId);
m_knownLumiDevices.insert("lumi.relay", lumiRelayThingClassId);
}
QString IntegrationPluginZigbeeLumi::name() const
@ -136,7 +142,6 @@ bool IntegrationPluginZigbeeLumi::handleNode(ZigbeeNode *node, const QUuid &netw
params << Param(m_zigbeeAddressParamTypeIds.value(thingClassId), node->extendedAddress().toString());
descriptor.setParams(params);
emit autoThingsAppeared({descriptor});
return true;
}
@ -437,6 +442,47 @@ void IntegrationPluginZigbeeLumi::setupThing(ThingSetupInfo *info)
}
}
if (thing->thingClassId() == lumiRelayThingClassId) {
// Get the 2 endpoints
ZigbeeNodeEndpoint *endpoint1 = node->getEndpoint(0x01);
if (!endpoint1) {
ZigbeeClusterOnOff *onOffCluster = endpoint1->inputCluster<ZigbeeClusterOnOff>(ZigbeeClusterLibrary::ClusterIdOnOff);
if (onOffCluster) {
if (onOffCluster->hasAttribute(ZigbeeClusterOnOff::AttributeOnOff)) {
thing->setStateValue(lumiRelayRelay1StateTypeId, onOffCluster->power());
}
connect(onOffCluster, &ZigbeeClusterOnOff::powerChanged, thing, [thing](bool power){
qCDebug(dcZigbeeLumi()) << thing << "power changed" << power;
thing->setStateValue(lumiRelayRelay1StateTypeId, power);
});
} else {
qCWarning(dcZigbeeLumi()) << "Could not find the OnOff input cluster on" << thing << endpoint1;
}
} else {
qCWarning(dcZigbeeLumi()) << "Could not find endpoint 1 on" << thing << node;
}
ZigbeeNodeEndpoint *endpoint2 = node->getEndpoint(0x02);
if (!endpoint2) {
ZigbeeClusterOnOff *onOffCluster = endpoint2->inputCluster<ZigbeeClusterOnOff>(ZigbeeClusterLibrary::ClusterIdOnOff);
if (onOffCluster) {
if (onOffCluster->hasAttribute(ZigbeeClusterOnOff::AttributeOnOff)) {
thing->setStateValue(lumiRelayRelay2StateTypeId, onOffCluster->power());
}
connect(onOffCluster, &ZigbeeClusterOnOff::powerChanged, thing, [thing](bool power){
qCDebug(dcZigbeeLumi()) << thing << "power changed" << power;
thing->setStateValue(lumiRelayRelay2StateTypeId, power);
});
} else {
qCWarning(dcZigbeeLumi()) << "Could not find the OnOff input cluster on" << thing << endpoint1;
}
} else {
qCWarning(dcZigbeeLumi()) << "Could not find endpoint 2 on" << thing << node;
}
}
info->finish(Thing::ThingErrorNoError);
}
@ -447,7 +493,7 @@ void IntegrationPluginZigbeeLumi::executeAction(ThingActionInfo *info)
if (thing->thingClassId() == lumiPowerSocketThingClassId) {
ZigbeeNode *node = m_thingNodes.value(thing);
if (!node) {
qCWarning(dcZigbeeLumi()) << "Zigbee node for" << thing->name() << "not found.";
qCWarning(dcZigbeeLumi()) << "Zigbee node for" << thing << "not found.";
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
@ -483,6 +529,69 @@ void IntegrationPluginZigbeeLumi::executeAction(ThingActionInfo *info)
return;
}
if (thing->thingClassId() == lumiRelayThingClassId) {
ZigbeeNode *node = m_thingNodes.value(thing);
if (!node) {
qCWarning(dcZigbeeLumi()) << "Zigbee node for" << thing << "not found.";
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
if (info->action().actionTypeId() == lumiRelayRelay1ActionTypeId) {
ZigbeeNodeEndpoint *endpoint = node->getEndpoint(0x01);
if (!endpoint) {
qCWarning(dcZigbeeLumi()) << "Unable to get the endpoint from node" << node << "for" << thing;
info->finish(Thing::ThingErrorSetupFailed);
return;
}
ZigbeeClusterOnOff *onOffCluster = endpoint->inputCluster<ZigbeeClusterOnOff>(ZigbeeClusterLibrary::ClusterIdOnOff);
if (!onOffCluster) {
qCWarning(dcZigbeeLumi()) << "Unable to get the OnOff cluster from endpoint" << endpoint << "on" << node << "for" << thing;
info->finish(Thing::ThingErrorSetupFailed);
return;
}
bool power = info->action().param(lumiRelayRelay1ActionRelay1ParamTypeId).value().toBool();
ZigbeeClusterReply *reply = (power ? onOffCluster->commandOn() : onOffCluster->commandOff());
connect(reply, &ZigbeeClusterReply::finished, this, [=](){
// Note: reply will be deleted automatically
if (reply->error() != ZigbeeClusterReply::ErrorNoError) {
info->finish(Thing::ThingErrorHardwareFailure);
} else {
info->finish(Thing::ThingErrorNoError);
thing->setStateValue(lumiRelayRelay1StateTypeId, power);
}
});
}
if (info->action().actionTypeId() == lumiRelayRelay2ActionTypeId) {
ZigbeeNodeEndpoint *endpoint = node->getEndpoint(0x02);
if (!endpoint) {
qCWarning(dcZigbeeLumi()) << "Unable to get the endpoint from node" << node << "for" << thing;
info->finish(Thing::ThingErrorSetupFailed);
return;
}
ZigbeeClusterOnOff *onOffCluster = endpoint->inputCluster<ZigbeeClusterOnOff>(ZigbeeClusterLibrary::ClusterIdOnOff);
if (!onOffCluster) {
qCWarning(dcZigbeeLumi()) << "Unable to get the OnOff cluster from endpoint" << endpoint << "on" << node << "for" << thing;
info->finish(Thing::ThingErrorSetupFailed);
return;
}
bool power = info->action().param(lumiRelayRelay2ActionRelay2ParamTypeId).value().toBool();
ZigbeeClusterReply *reply = (power ? onOffCluster->commandOn() : onOffCluster->commandOff());
connect(reply, &ZigbeeClusterReply::finished, this, [=](){
// Note: reply will be deleted automatically
if (reply->error() != ZigbeeClusterReply::ErrorNoError) {
info->finish(Thing::ThingErrorHardwareFailure);
} else {
info->finish(Thing::ThingErrorNoError);
thing->setStateValue(lumiRelayRelay2StateTypeId, power);
}
});
}
}
info->finish(Thing::ThingErrorUnsupportedFeature);
}