diff --git a/bindings.cpp b/bindings.cpp index 454825159f..f645197e9c 100644 --- a/bindings.cpp +++ b/bindings.cpp @@ -1163,6 +1163,7 @@ bool DeRestPluginPrivate::sendConfigureReportingRequest(BindingTask &bt) sensor->modelId() == QLatin1String("multiv4") || sensor->modelId() == QLatin1String("RFDL-ZB-MS") || sensor->modelId() == QLatin1String("Zen-01") || + sensor->modelId() == QLatin1String("Bell") || sensor->modelId().startsWith(QLatin1String("3315")))) { rq.attributeId = 0x0020; // battery voltage @@ -1244,7 +1245,8 @@ bool DeRestPluginPrivate::sendConfigureReportingRequest(BindingTask &bt) rq.maxInterval = 300; if (sensor && (sensor->modelId() == QLatin1String("SmartPlug") || // Heiman sensor->modelId() == QLatin1String("SKHMP30-I1") || // GS smart plug - sensor->modelId().startsWith(QLatin1String("E13-")))) // Sengled PAR38 Bulbs + sensor->modelId().startsWith(QLatin1String("E13-")) || // Sengled PAR38 Bulbs + sensor->modelId().startsWith(QLatin1String("Connected s")))) // Niko smart socket { rq.reportableChange48bit = 10; // 0.001 kWh (1 Wh) } @@ -1252,7 +1254,8 @@ bool DeRestPluginPrivate::sendConfigureReportingRequest(BindingTask &bt) { rq.reportableChange48bit = 1000; // 0.001 kWh (1 Wh) } - else if (sensor && (sensor->modelId().startsWith(QLatin1String("ROB_200")))) // ROBB Smarrt micro dimmer + else if (sensor && (sensor->modelId().startsWith(QLatin1String("ROB_200")) || // ROBB Smarrt micro dimmer + sensor->modelId().startsWith(QLatin1String("Micro Smart Dimmer")))) // Sunricher Micro Smart Dimmer { rq.reportableChange48bit = 3600; // 0.001 kWh (1 Wh) } @@ -1268,7 +1271,8 @@ bool DeRestPluginPrivate::sendConfigureReportingRequest(BindingTask &bt) rq2.maxInterval = 300; if (sensor && (sensor->modelId() == QLatin1String("SmartPlug") || // Heiman sensor->modelId() == QLatin1String("902010/25") || // Bitron - sensor->modelId() == QLatin1String("SKHMP30-I1"))) // GS smart plug + sensor->modelId() == QLatin1String("SKHMP30-I1") ||// GS smart plug + sensor->modelId() == QLatin1String("160-01"))) // Plugwise smart plug { rq2.reportableChange24bit = 10; // 1 W } @@ -1294,7 +1298,9 @@ bool DeRestPluginPrivate::sendConfigureReportingRequest(BindingTask &bt) if (sensor && (sensor->modelId() == QLatin1String("SmartPlug") || // Heiman sensor->modelId() == QLatin1String("SKHMP30-I1") || // GS smart plug sensor->modelId() == QLatin1String("SZ-ESW01-AU") || // Sercomm / Telstra smart plug - sensor->modelId().startsWith(QLatin1String("ROB_200")))) // ROBB Smarrt micro dimmer + sensor->modelId().startsWith(QLatin1String("ROB_200")) || // ROBB Smarrt micro dimmer + sensor->modelId().startsWith(QLatin1String("Micro Smart Dimmer")) || // Sunricher Micro Smart Dimmer + sensor->modelId().startsWith(QLatin1String("lumi.plug.maeu")))) // Xiaomi Aqara ZB3.0 smart plug { rq.reportableChange16bit = 10; // 1 W } @@ -1317,7 +1323,10 @@ bool DeRestPluginPrivate::sendConfigureReportingRequest(BindingTask &bt) { rq2.reportableChange16bit = 125; // 1 V } - else if (sensor && sensor->modelId().startsWith(QLatin1String("ROB_200"))) // ROBB Smarrt micro dimmer + else if (sensor && (sensor->modelId().startsWith(QLatin1String("ROB_200")) || // ROBB Smarrt micro dimmer + sensor->modelId().startsWith(QLatin1String("Micro Smart Dimmer")) || // Sunricher Micro Smart Dimmer + sensor->modelId().startsWith(QLatin1String("Connected s")) || // Niko smart socket + sensor->modelId().startsWith(QLatin1String("TH112")))) // Sinope Thermostats { rq2.reportableChange16bit = 10; // 1 V } @@ -1333,7 +1342,9 @@ bool DeRestPluginPrivate::sendConfigureReportingRequest(BindingTask &bt) rq3.maxInterval = 300; if (sensor && (sensor->modelId() == QLatin1String("SP 120") || // innr sensor->modelId() == QLatin1String("DoubleSocket50AU") || // Aurora - sensor->modelId() == QLatin1String("SZ-ESW01-AU"))) // Sercomm / Telstra smart plug + sensor->modelId() == QLatin1String("SZ-ESW01-AU") || // Sercomm / Telstra smart plug + sensor->modelId().startsWith(QLatin1String("Connected s")) || // Niko smart socket + sensor->modelId() == QLatin1String("TS0121"))) // Tuya / Blitzwolf { rq3.reportableChange16bit = 100; // 0.1 A } @@ -1915,6 +1926,7 @@ bool DeRestPluginPrivate::checkSensorBindingsForAttributeReporting(Sensor *senso sensor->modelId().startsWith(QLatin1String("DC_")) || sensor->modelId().startsWith(QLatin1String("PSMD_")) || sensor->modelId().startsWith(QLatin1String("PSMP5_")) || + sensor->modelId().startsWith(QLatin1String("PCM_")) || // CentraLite sensor->modelId().startsWith(QLatin1String("Motion Sensor-A")) || sensor->modelId().startsWith(QLatin1String("332")) || @@ -1980,6 +1992,7 @@ bool DeRestPluginPrivate::checkSensorBindingsForAttributeReporting(Sensor *senso sensor->modelId().startsWith(QLatin1String("PIRS")) || sensor->modelId().startsWith(QLatin1String("SKHMP30")) || // GS smart plug sensor->modelId().startsWith(QLatin1String("RC_V14")) || + sensor->modelId().startsWith(QLatin1String("RC-EM")) || // Konke sensor->modelId() == QLatin1String("3AFE140103020000") || sensor->modelId() == QLatin1String("3AFE130104020015") || @@ -2010,6 +2023,7 @@ bool DeRestPluginPrivate::checkSensorBindingsForAttributeReporting(Sensor *senso sensor->modelId() == QLatin1String("LG IP65 HMS") || // Sinope sensor->modelId() == QLatin1String("WL4200S") || + sensor->modelId().startsWith(QLatin1String("TH112")) || //LifeControl smart plug sensor->modelId() == QLatin1String("RICI01") || //LifeControl enviroment sensor @@ -2052,6 +2066,7 @@ bool DeRestPluginPrivate::checkSensorBindingsForAttributeReporting(Sensor *senso // Tuya sensor->modelId().startsWith(QLatin1String("TS01")) || sensor->modelId().startsWith(QLatin1String("TS02")) || + sensor->modelId().startsWith(QLatin1String("TS03")) || // Tuyatec sensor->modelId().startsWith(QLatin1String("RH3040")) || sensor->modelId().startsWith(QLatin1String("RH3001")) || @@ -2081,7 +2096,18 @@ bool DeRestPluginPrivate::checkSensorBindingsForAttributeReporting(Sensor *senso // Embertec sensor->modelId().startsWith(QLatin1String("BQZ10-AU")) || // ROBB Smarrt - sensor->modelId().startsWith(QLatin1String("ROB_200"))) + sensor->modelId().startsWith(QLatin1String("ROB_200")) || + // Sunricher + sensor->modelId().startsWith(QLatin1String("Micro Smart Dimmer")) || + sensor->modelId().startsWith(QLatin1String("451270")) || + // EcoDim + sensor->modelId().startsWith(QLatin1String("ED-1001")) || + // Plugwise + sensor->modelId().startsWith(QLatin1String("160-01")) || + // Niko + sensor->modelId() == QLatin1String("Connected socket outlet") || + // Sage + sensor->modelId() == QLatin1String("Bell")) { deviceSupported = true; if (!sensor->node()->nodeDescriptor().receiverOnWhenIdle() || @@ -2576,6 +2602,16 @@ bool DeRestPluginPrivate::checkSensorBindingsForClientClusters(Sensor *sensor) srcEndpoints.push_back(0x03); srcEndpoints.push_back(0x04); } + else if (sensor->modelId().startsWith(QLatin1String("ED-1001"))) + { + clusters.push_back(ONOFF_CLUSTER_ID); + clusters.push_back(LEVEL_CLUSTER_ID); + clusters.push_back(SCENE_CLUSTER_ID); + srcEndpoints.push_back(0x01); + srcEndpoints.push_back(0x02); + srcEndpoints.push_back(0x03); + srcEndpoints.push_back(0x04); + } else if (sensor->modelId().startsWith(QLatin1String("D1"))) { clusters.push_back(ONOFF_CLUSTER_ID); @@ -2621,7 +2657,8 @@ bool DeRestPluginPrivate::checkSensorBindingsForClientClusters(Sensor *sensor) srcEndpoints.push_back(sensor->fingerPrint().endpoint); } // Heiman remote control - else if (sensor->modelId().startsWith(QLatin1String("RC_V14"))) + else if (sensor->modelId().startsWith(QLatin1String("RC_V14")) || + sensor->modelId().startsWith(QLatin1String("RC-EM"))) { clusters.push_back(IAS_ACE_CLUSTER_ID); srcEndpoints.push_back(sensor->fingerPrint().endpoint); @@ -2642,6 +2679,13 @@ bool DeRestPluginPrivate::checkSensorBindingsForClientClusters(Sensor *sensor) srcEndpoints.push_back(0x01); srcEndpoints.push_back(0x02); } + // Sage doorbell sensor + else if (sensor->modelId().startsWith(QLatin1String("Bell"))) + { + clusters.push_back(ONOFF_CLUSTER_ID); + clusters.push_back(LEVEL_CLUSTER_ID); + srcEndpoints.push_back(sensor->fingerPrint().endpoint); + } else { return false; @@ -2764,7 +2808,8 @@ void DeRestPluginPrivate::checkSensorGroup(Sensor *sensor) sensor->modelId().startsWith(QLatin1String("TRADFRI remote control")) || sensor->modelId().startsWith(QLatin1String("TRADFRI wireless dimmer")) || // sensor->modelId().startsWith(QLatin1String("SYMFONISK")) || - sensor->modelId().startsWith(QLatin1String("902010/23"))) // bitron remote + sensor->modelId().startsWith(QLatin1String("902010/23")) || // bitron remote + sensor->modelId().startsWith(QLatin1String("Bell")) // Sage doorbell sensor { } diff --git a/database.cpp b/database.cpp index f7f4af5be1..c3e7bb8588 100644 --- a/database.cpp +++ b/database.cpp @@ -3186,8 +3186,11 @@ static int sqliteLoadAllSensorsCallback(void *user, int ncols, char **colval , c { clusterId = clusterId ? clusterId : ANALOG_INPUT_CLUSTER_ID; } - item = sensor.addItem(DataTypeUInt64, RStateConsumption); - item->setValue(0); + if (modelId != QLatin1String("160-01")) + { + item = sensor.addItem(DataTypeUInt64, RStateConsumption); + item->setValue(0); + } } else if (sensor.type().endsWith(QLatin1String("Power"))) { @@ -3370,6 +3373,8 @@ static int sqliteLoadAllSensorsCallback(void *user, int ncols, char **colval , c if (!sensor.modelId().startsWith(QLatin1String("lumi.ctrl_")) && !sensor.modelId().startsWith(QLatin1String("lumi.plug")) && sensor.modelId() != QLatin1String("lumi.curtain") && + sensor.modelId() != QLatin1String("lumi.sensor_natgas") && + !sensor.modelId().startsWith(QLatin1String("lumi.relay.c")) && !sensor.type().endsWith(QLatin1String("Battery"))) { item = sensor.addItem(DataTypeUInt8, RConfigBattery); diff --git a/de_web_plugin.cpp b/de_web_plugin.cpp index 4d79ac13b0..763f948b6e 100644 --- a/de_web_plugin.cpp +++ b/de_web_plugin.cpp @@ -68,6 +68,7 @@ const quint64 macPrefixMask = 0xffffff0000000000ULL; // New mac prefixes can be checked here: https://wintelguy.com/index.pl const quint64 legrandMacPrefix = 0x0004740000000000ULL; +const quint64 dishMacPrefix = 0x0008890000000000ULL; const quint64 ikeaMacPrefix = 0x000b570000000000ULL; const quint64 emberMacPrefix = 0x000d6f0000000000ULL; const quint64 instaMacPrefix = 0x000f170000000000ULL; @@ -91,9 +92,11 @@ const quint64 profaluxMacPrefix = 0x20918a0000000000ULL; const quint64 stMacPrefix = 0x24fd5b0000000000ULL; const quint64 samjinMacPrefix = 0x286d970000000000ULL; const quint64 sinopeMacPrefix = 0x500b910000000000ULL; +const quint64 silabs6MacPrefix = 0x588e810000000000ULL; const quint64 silabs4MacPrefix = 0x680ae20000000000ULL; const quint64 ecozyMacPrefix = 0x70b3d50000000000ULL; const quint64 osramMacPrefix = 0x8418260000000000ULL; +const quint64 silabs5MacPrefix = 0x842e140000000000ULL; const quint64 embertecMacPrefix = 0x848e960000000000ULL; const quint64 silabsMacPrefix = 0x90fd9f0000000000ULL; const quint64 zhejiangMacPrefix = 0xb0ce180000000000ULL; @@ -136,6 +139,7 @@ static const SupportedDevice supportedDevices[] = { { VENDOR_NONE, "BX_", tiMacPrefix }, // Climax siren { VENDOR_NONE, "PSMD_", tiMacPrefix }, // Climax smart plug { VENDOR_NONE, "PSMP5_", tiMacPrefix }, // Climax smart plug + { VENDOR_NONE, "PCM_", tiMacPrefix }, // Climax power meter { VENDOR_NONE, "OJB-IR715-Z", tiMacPrefix }, { VENDOR_NONE, "902010/21", tiMacPrefix }, // Bitron: door/window sensor { VENDOR_NONE, "902010/22", tiMacPrefix }, // Bitron: motion sensor @@ -193,6 +197,7 @@ static const SupportedDevice supportedDevices[] = { { VENDOR_JENNIC, "lumi.vibration", jennicMacPrefix }, // Xiaomi Aqara vibration/shock sensor { VENDOR_JENNIC, "lumi.sensor_wleak", jennicMacPrefix }, { VENDOR_JENNIC, "lumi.sensor_smoke", jennicMacPrefix }, + { VENDOR_JENNIC, "lumi.sensor_natgas", jennicMacPrefix }, // Xiaomi Mija (HonneyWell) gas detector { VENDOR_JENNIC, "lumi.relay.c", jennicMacPrefix }, // Xiaomi Aqara LLKZMK11LM { VENDOR_XIAOMI, "lumi.plug", jennicMacPrefix }, // Xiaomi smart plug (router) { VENDOR_XIAOMI, "lumi.ctrl_ln", jennicMacPrefix}, // Xiaomi Wall Switch (router) @@ -232,6 +237,7 @@ static const SupportedDevice supportedDevices[] = { { VENDOR_HEIMAN, "Smoke", jennicMacPrefix }, // Heiman fire sensor - newer model { VENDOR_HEIMAN, "PIRS", jennicMacPrefix }, // Heiman motion sensor - newer model { VENDOR_HEIMAN, "SKHMP30", jennicMacPrefix }, // GS (Heiman) smart plug + { VENDOR_HEIMAN, "RC-EM", emberMacPrefix }, // Heiman IAS ACE remote control { VENDOR_LUTRON, "LZL4BWHL01", lutronMacPrefix }, // Lutron LZL-4B-WH-L01 Connected Bulb Remote { VENDOR_LUTRON, "Z3-1BRL", lutronMacPrefix }, // Lutron Aurora Friends-of-Hue dimmer { VENDOR_KEEN_HOME , "SV01-", keenhomeMacPrefix}, // Keen Home Vent @@ -241,16 +247,19 @@ static const SupportedDevice supportedDevices[] = { { VENDOR_JENNIC, "ZYCT-202", jennicMacPrefix }, // Trust remote control ZYCT-202 { VENDOR_INNR, "RC 110", jennicMacPrefix }, // innr remote RC 110 { VENDOR_VISONIC, "MCT-340", emberMacPrefix }, // Visonic MCT-340 E temperature/motion + { VENDOR_SUNRICHER, "ED-1001", silabs2MacPrefix }, // EcoDim wireless switches { VENDOR_SUNRICHER, "ICZB-KPD1", emberMacPrefix }, // iCasa keypad { VENDOR_SUNRICHER, "ICZB-RM", silabs2MacPrefix }, // iCasa remote { VENDOR_SUNRICHER, "ZGRC-KEY", emberMacPrefix }, // Sunricher wireless CCT remote { VENDOR_SUNRICHER, "ZG2833K", emberMacPrefix }, // Sunricher remote controller { VENDOR_SUNRICHER, "RGBgenie ZB-5", emberMacPrefix }, // RGBgenie remote control - { VENDOR_SUNRICHER, "ROB_200", silabs2MacPrefix }, // Sunricher SR-ZG9040A built-in dimmer, whitelabeled by Robbshop + { VENDOR_SUNRICHER, "ROB_200", silabs3MacPrefix }, // Sunricher SR-ZG9040A built-in dimmer, whitelabeled by Robbshop + { VENDOR_SUNRICHER, "Micro Smart Dimmer", silabs3MacPrefix }, // Sunricher SR-ZG9040A built-in dimmer { VENDOR_JENNIC, "SPZB0001", jennicMacPrefix }, // Eurotronic thermostat { VENDOR_NONE, "RES001", tiMacPrefix }, // Hubitat environment sensor, see #1308 { VENDOR_SINOPE, "WL4200S", sinopeMacPrefix}, // Sinope water sensor { VENDOR_SINOPE, "TH1300ZB", sinopeMacPrefix }, // Sinope Thermostat + { VENDOR_SINOPE, "TH112", sinopeMacPrefix }, // Sinope Thermostat TH1123ZB & TH1124ZB { VENDOR_ZEN, "Zen-01", zenMacPrefix }, // Zen Thermostat { VENDOR_C2DF, "3157100", emberMacPrefix }, // Centralite Thermostat { VENDOR_EMBER, "Super TR", emberMacPrefix }, // Elko Thermostat @@ -294,6 +303,8 @@ static const SupportedDevice supportedDevices[] = { { VENDOR_EMBER, "TS0201", silabs3MacPrefix }, // Tuya/Blitzwolf temperature and humidity sensor { VENDOR_NONE, "TS0204", silabs3MacPrefix }, // Tuya gas sensor { VENDOR_NONE, "TS0121", silabs3MacPrefix }, // Tuya/Blitzwolf smart plug + { VENDOR_EMBER, "TS0121", silabs3MacPrefix }, // Tuya/Blitzwolf smart plug + { VENDOR_EMBER, "TS0302", silabs3MacPrefix }, // Tuya curtain switch { VENDOR_AURORA, "DoubleSocket50AU", jennicMacPrefix }, // Aurora AOne Double Socket UK { VENDOR_COMPUTIME, "SP600", computimeMacPrefix }, // Salus smart plug { VENDOR_HANGZHOU_IMAGIC, "1116-S", energyMiMacPrefix }, // iris contact sensor v3 @@ -305,7 +316,7 @@ static const SupportedDevice supportedDevices[] = { { VENDOR_SERCOMM, "SZ-DWS04", emberMacPrefix }, // Sercomm open/close sensor { VENDOR_SERCOMM, "Tripper", emberMacPrefix }, // Quirky Tripper (Sercomm) open/close sensor { VENDOR_ALERTME, "MOT003", tiMacPrefix }, // Hive Motion Sensor - { VENDOR_SUNRICHER, "4512703", silabs2MacPrefix }, // Namron 4-ch remote controller + { VENDOR_SUNRICHER, "451270", silabs2MacPrefix }, // Namron 1/4-ch remote controller { VENDOR_SENGLED_OPTOELEC, "E13-", zhejiangMacPrefix }, // Sengled PAR38 Bulbs { VENDOR_SENGLED_OPTOELEC, "E1D-", zhejiangMacPrefix }, // Sengled contact sensor { VENDOR_JENNIC, "Plug-230V-ZB3.0", silabs2MacPrefix }, // Immax NEO ZB3.0 smart plug @@ -314,6 +325,9 @@ static const SupportedDevice supportedDevices[] = { { VENDOR_PHILIO, "PST03A-v2.2.5", emberMacPrefix }, // Philio pst03-a { VENDOR_EMBERTEC, "BQZ10-AU", embertecMacPrefix }, // Embertec smart plug { VENDOR_MUELLER, "ZBT-Remote-ALL-RGBW", jennicMacPrefix }, // Tint remote control + { VENDOR_PLUGWISE_BV, "160-01", emberMacPrefix }, // Plugwise smart plug + { VENDOR_NIKO_NV, "Connected socket outlet", konkeMacPrefix }, // Niko smart socket 170-33505 + { VENDOR_ATMEL, "Bell", dishMacPrefix }, // Sage doorbell sensor { 0, nullptr, 0 } }; @@ -813,6 +827,27 @@ void DeRestPluginPrivate::apsdeDataIndication(const deCONZ::ApsDataIndication &i { case ZDP_NODE_DESCRIPTOR_RSP_CLID: { + // Safeguard to issue a 2nd active endpoint request in case the first one got MIA + // Temporary workaround till state machine is available (request is fired ruthless) + deCONZ::ApsDataRequest apsReq; + + // ZDP Header + apsReq.dstAddress() = ind.srcAddress(); + apsReq.setDstAddressMode(deCONZ::ApsNwkAddress); + apsReq.setDstEndpoint(ZDO_ENDPOINT); + apsReq.setSrcEndpoint(ZDO_ENDPOINT); + apsReq.setProfileId(ZDP_PROFILE_ID); + apsReq.setRadius(0); + apsReq.setClusterId(ZDP_ACTIVE_ENDPOINTS_CLID); + + QDataStream stream(&apsReq.asdu(), QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + + stream << zclSeq++; + stream << ind.srcAddress().nwk(); + + apsCtrl->apsdeDataRequest(apsReq); // Fire and forget + handleNodeDescriptorResponseIndication(ind); handleIndicationSearchSensors(ind, zclFrame); } @@ -3278,7 +3313,8 @@ void DeRestPluginPrivate::checkSensorButtonEvent(Sensor *sensor, const deCONZ::A checkClientCluster = true; } else if (sensor->modelId().startsWith(QLatin1String("RC 110")) || // innr remote - sensor->modelId().startsWith(QLatin1String("RC_V14"))) // Heiman remote + sensor->modelId().startsWith(QLatin1String("RC_V14")) || // Heiman remote + sensor->modelId().startsWith(QLatin1String("RC-EM"))) // Heiman remote { checkClientCluster = true; } @@ -3294,6 +3330,19 @@ void DeRestPluginPrivate::checkSensorButtonEvent(Sensor *sensor, const deCONZ::A { checkReporting = true; } + else if (sensor->modelId() == QLatin1String("Bell")) //Sage doorbell sensor + { + if (ind.dstAddressMode() == deCONZ::ApsGroupAddress && ind.dstAddress().group() == 0) + { + checkClientCluster = true; + checkReporting = true; + ResourceItem *item = sensor->item(RConfigGroup); + if (!item || (item && (item->toString() == QLatin1String("0") || item->toString().isEmpty()))) + { + checkSensorGroup(sensor); // still default group, create unique group and binding + } + } + } if (ind.dstAddressMode() == deCONZ::ApsGroupAddress && ind.dstAddress().group() != 0) { @@ -3646,7 +3695,8 @@ void DeRestPluginPrivate::checkSensorButtonEvent(Sensor *sensor, const deCONZ::A zclFrame.commandId() == 0x07) ) // stop (with on/off) { ok = false; - if (buttonMap->zclParam0 == sensor->previousDirection) // direction of previous move/step + if (buttonMap->zclParam0 == sensor->previousDirection || // direction of previous move/step + sensor->modelId().startsWith(QLatin1String("RGBgenie ZB-5121"))) // Device sends cmd = 7 + param = 0 for dim up/down { sensor->previousDirection = 0xFF; ok = true; @@ -4088,6 +4138,11 @@ void DeRestPluginPrivate::addSensorNode(const deCONZ::Node *node, const deCONZ:: { fpSwitch.inClusters.push_back(MULTISTATE_INPUT_CLUSTER_ID); } + else if (node->nodeDescriptor().manufacturerCode() == VENDOR_JENNIC && + modelId.startsWith(QLatin1String("lumi.sensor_natgas"))) + { + fpCarbonMonoxideSensor.inClusters.push_back(IAS_ZONE_CLUSTER_ID); + } } break; @@ -4168,7 +4223,8 @@ void DeRestPluginPrivate::addSensorNode(const deCONZ::Node *node, const deCONZ:: case IAS_ZONE_CLUSTER_ID: { if (modelId.startsWith(QLatin1String("CO_")) || // Heiman CO sensor - modelId.startsWith(QLatin1String("COSensor"))) // Heiman CO sensor (newer model) + modelId.startsWith(QLatin1String("COSensor")) || // Heiman CO sensor (newer model) + modelId.startsWith(QLatin1String("lumi.sensor_natgas"))) // Xiaomi Mi gas detector { fpCarbonMonoxideSensor.inClusters.push_back(ci->id()); } @@ -4438,7 +4494,7 @@ void DeRestPluginPrivate::addSensorNode(const deCONZ::Node *node, const deCONZ:: case ELECTRICAL_MEASUREMENT_CLUSTER_ID: { - if(modelId != QLatin1String("lumi.plug.mmeu01") && modelId != QLatin1String("lumi.relay.c2acn01")) + if(modelId != QLatin1String("lumi.plug.mmeu01") && modelId != QLatin1String("160-01")) { fpPowerSensor.inClusters.push_back(ci->id()); } @@ -4543,7 +4599,7 @@ void DeRestPluginPrivate::addSensorNode(const deCONZ::Node *node, const deCONZ:: case IAS_ACE_CLUSTER_ID: { - if (modelId == QLatin1String("RC_V14")) + if (modelId == QLatin1String("RC_V14") || modelId == QLatin1String("RC-EM")) { fpSwitch.outClusters.push_back(ci->id()); } @@ -5233,7 +5289,10 @@ void DeRestPluginPrivate::addSensorNode(const deCONZ::Node *node, const SensorFi if (sensorNode.fingerPrint().hasInCluster(METERING_CLUSTER_ID)) { clusterId = METERING_CLUSTER_ID; - item = sensorNode.addItem(DataTypeUInt64, RStateConsumption); + if (modelId != QLatin1String("160-01")) + { + item = sensorNode.addItem(DataTypeUInt64, RStateConsumption); + } if ((modelId != QLatin1String("SP 120")) && (modelId != QLatin1String("ZB-ONOFFPlug-D0005")) && (modelId != QLatin1String("TS0121")) && @@ -5479,7 +5538,9 @@ void DeRestPluginPrivate::addSensorNode(const deCONZ::Node *node, const SensorFi sensorNode.setManufacturer("LUMI"); if (!sensorNode.modelId().startsWith(QLatin1String("lumi.ctrl_")) && !sensorNode.modelId().startsWith(QLatin1String("lumi.plug")) && + !sensorNode.modelId().startsWith(QLatin1String("lumi.relay.c")) && sensorNode.modelId() != QLatin1String("lumi.curtain") && + sensorNode.modelId() != QLatin1String("lumi.sensor_natgas") && !sensorNode.type().endsWith(QLatin1String("Battery"))) { sensorNode.addItem(DataTypeUInt8, RConfigBattery); @@ -6187,10 +6248,11 @@ void DeRestPluginPrivate::updateSensorNode(const deCONZ::NodeEvent &event) i->modelId().startsWith(QLatin1String("KADRILJ")) || // IKEA i->modelId().startsWith(QLatin1String("SYMFONISK")) || // IKEA i->modelId().startsWith(QLatin1String("ICZB-")) || // iCasa keypads and remote + i->modelId().startsWith(QLatin1String("ED-1001")) || // EcoDim wireless switches i->modelId().startsWith(QLatin1String("ZGRC-KEY")) || // Sunricher wireless CCT remote i->modelId().startsWith(QLatin1String("ZG2833K")) || // Sunricher remote controller i->modelId().startsWith(QLatin1String("SV01-")) || // Keen Home vent - i->modelId().startsWith(QLatin1String("4512703")) || // Namron 4-ch remote controller + i->modelId().startsWith(QLatin1String("451270")) || // Namron 1/4-ch remote controller i->modelId().startsWith(QLatin1String("RGBgenie ZB-5")) || // RGBgenie remote control i->modelId().startsWith(QLatin1String("VOC_Sensor"))) // LifeControl Enviroment sensor { @@ -6224,10 +6286,11 @@ void DeRestPluginPrivate::updateSensorNode(const deCONZ::NodeEvent &event) if (i->modelId().startsWith(QLatin1String("TRADFRI")) || // IKEA i->modelId().startsWith(QLatin1String("SYMFONISK")) || // IKEA i->modelId().startsWith(QLatin1String("ICZB-")) || // iCasa keypads and remote + i->modelId().startsWith(QLatin1String("ED-1001")) || // EcoDim wireless switches i->modelId().startsWith(QLatin1String("ZGRC-KEY")) || // Sunricher wireless CCT remote i->modelId().startsWith(QLatin1String("ZG2833K")) || // Sunricher remote controller i->modelId().startsWith(QLatin1String("SV01-")) || // Keen Home vent - i->modelId().startsWith(QLatin1String("4512703")) || // Namron 4-ch remote controller + i->modelId().startsWith(QLatin1String("451270")) || // Namron 1/4-ch remote controller i->modelId().startsWith(QLatin1String("RGBgenie ZB-5")) || // RGBgenie remote control i->modelId().startsWith(QLatin1String("VOC_Sensor"))) // LifeControl Enviroment sensor { @@ -6260,6 +6323,7 @@ void DeRestPluginPrivate::updateSensorNode(const deCONZ::NodeEvent &event) i->modelId() == QLatin1String("Zen-01") || // Zen thermostat i->modelId() == QLatin1String("Thermostat") || // eCozy thermostat i->modelId() == QLatin1String("Motion Sensor-A") || // Osram motion sensor + i->modelId() == QLatin1String("Bell") || // Sage doorbell sensor i->modelId().endsWith(QLatin1String("86opcn01")) || // Aqara Opple i->modelId().startsWith(QLatin1String("SMSZB-120")) || // Develco smoke sensor i->modelId().startsWith(QLatin1String("HESZB-120")) || // Develco heat sensor @@ -7362,12 +7426,14 @@ void DeRestPluginPrivate::updateSensorNode(const deCONZ::NodeEvent &event) if (i->modelId() == QLatin1String("SmartPlug") || // Heiman i->modelId().startsWith(QLatin1String("PSMP5_")) || // Climax i->modelId().startsWith(QLatin1String("SKHMP30")) || // GS smart plug - i->modelId().startsWith(QLatin1String("E13-"))) // Sengled PAR38 Bulbs + i->modelId().startsWith(QLatin1String("E13-")) || // Sengled PAR38 Bulbs + i->modelId().startsWith(QLatin1String("Connected s"))) // Niko smart socket { consumption += 5; consumption /= 10; // 0.1 Wh -> Wh } else if (i->modelId() == QLatin1String("SP 120") || // innr - i->modelId() == QLatin1String("Plug-230V-ZB3.0")) // Immax + i->modelId() == QLatin1String("Plug-230V-ZB3.0") || // Immax + i->modelId() == QLatin1String("TS0121")) // Tuya / Blitzwolf { consumption *= 10; // 0.01 kWh = 10 Wh -> Wh } @@ -7375,7 +7441,8 @@ void DeRestPluginPrivate::updateSensorNode(const deCONZ::NodeEvent &event) { consumption /= 1000; } - else if (i->modelId().startsWith(QLatin1String("ROB_200"))) // ROBB Smarrt micro dimmer + else if (i->modelId().startsWith(QLatin1String("ROB_200")) || // ROBB Smarrt micro dimmer + i->modelId().startsWith(QLatin1String("Micro Smart Dimmer"))) // Sunricher Micro Smart Dimmer { consumption /= 3600; } @@ -7401,7 +7468,8 @@ void DeRestPluginPrivate::updateSensorNode(const deCONZ::NodeEvent &event) if (i->modelId() == QLatin1String("SmartPlug") || // Heiman i->modelId() == QLatin1String("902010/25") || // Bitron i->modelId().startsWith(QLatin1String("PSMP5_")) || // Climax - i->modelId().startsWith(QLatin1String("SKHMP30"))) // GS smart plug + i->modelId().startsWith(QLatin1String("SKHMP30")) ||// GS smart plug + i->modelId().startsWith(QLatin1String("160-01"))) // Plugwise smart plug { power += 5; power /= 10; // 0.1 W -> W } @@ -7453,7 +7521,9 @@ void DeRestPluginPrivate::updateSensorNode(const deCONZ::NodeEvent &event) { if (i->modelId() == QLatin1String("SmartPlug") || // Heiman i->modelId().startsWith(QLatin1String("SKHMP30")) || // GS smart plug - i->modelId().startsWith(QLatin1String("ROB_200"))) // ROBB Smarrt micro dimmer + i->modelId().startsWith(QLatin1String("ROB_200")) || // ROBB Smarrt micro dimmer + i->modelId().startsWith(QLatin1String("Micro Smart Dimmer")) || // Sunricher Micro Smart Dimmer + i->modelId().startsWith(QLatin1String("lumi.plug.maeu"))) // Xiaomi Aqara ZB3.0 smart plug { power += 5; power /= 10; // 0.1W -> W } @@ -7471,6 +7541,14 @@ void DeRestPluginPrivate::updateSensorNode(const deCONZ::NodeEvent &event) { power *= 128; power /= 1000; } + else if (i->modelId().startsWith(QLatin1String("Connected s"))) // Niko smart socket + { + power *= 1123; power /= 10000; + } + else if (i->modelId().startsWith(QLatin1String("lumi.relay.c2acn"))) // Xiaomi relay + { + continue; // Device seems to always report -1 via this cluster/attribute + } item->setValue(power); // in W enqueueEvent(Event(RSensors, RStatePower, i->id(), item)); updated = true; @@ -7499,7 +7577,10 @@ void DeRestPluginPrivate::updateSensorNode(const deCONZ::NodeEvent &event) else if (i->modelId() == QLatin1String("RICI01") || // LifeControl Smart Plug i->modelId().startsWith(QLatin1String("outlet")) || // Samsung SmartThings IM6001-OTP/IM6001-OTP01 i->modelId() == QLatin1String("EMIZB-13") || // Develco EMI - i->modelId().startsWith(QLatin1String("ROB_200"))) // ROBB Smarrt micro dimmer + i->modelId().startsWith(QLatin1String("ROB_200")) || // ROBB Smarrt micro dimmer + i->modelId().startsWith(QLatin1String("Micro Smart Dimmer")) || // Sunricher Micro Smart Dimmer + i->modelId().startsWith(QLatin1String("Connected s")) || // Niko smart socket + i->modelId().startsWith(QLatin1String("TH112"))) // Sinope Thermostats { voltage /= 10; // 0.1V -> V } @@ -7531,7 +7612,13 @@ void DeRestPluginPrivate::updateSensorNode(const deCONZ::NodeEvent &event) i->modelId() == QLatin1String("RICI01") || // LifeControl Smart Plug i->modelId().startsWith(QLatin1String("SZ-ESW01")) || // Sercomm / Telstra smart plug i->modelId() == QLatin1String("TS0121") || // Tuya smart plug - i->modelId().startsWith(QLatin1String("ROB_200"))) // ROBB Smarrt micro dimmer + i->modelId().startsWith(QLatin1String("ROB_200")) || // ROBB Smarrt micro dimmer + i->modelId().startsWith(QLatin1String("Micro Smart Dimmer")) || // Sunricher Micro Smart Dimmer + i->modelId().startsWith(QLatin1String("Connected s")) || // Niko smart socket + i->modelId().startsWith(QLatin1String("S1")) || // Ubisys S1/S1-R + i->modelId().startsWith(QLatin1String("S2")) || // Ubisys S2/S2-R + i->modelId().startsWith(QLatin1String("J1")) || // Ubisys J1/J1-R + i->modelId().startsWith(QLatin1String("D1"))) // Ubisys D1/D1-R { // already in mA } @@ -10271,7 +10358,7 @@ void DeRestPluginPrivate::handleZclAttributeReportIndicationXiaomiSpecial(const DBG_Printf(DBG_INFO, "\t03 temperature %d °C\n", int(s8)); // Device temperature for lumi.plug.mmeu01 temperature = qint16(s8) * 100; } - else if (tag == 0x04 && dataType == deCONZ::Zcl16BitUint) + else if ((tag == 0x04 || structIndex == 0x03) && dataType == deCONZ::Zcl16BitUint) { DBG_Printf(DBG_INFO, "\t04 unknown %d (0x%04X)\n", u16, u16); } @@ -10279,7 +10366,7 @@ void DeRestPluginPrivate::handleZclAttributeReportIndicationXiaomiSpecial(const { DBG_Printf(DBG_INFO, "\t05 RSSI dB (?) %d (0x%04X)\n", u16, u16); } - else if (tag == 0x06 && dataType == deCONZ::Zcl40BitUint) + else if ((tag == 0x06 || structIndex == 0x04) && dataType == deCONZ::Zcl40BitUint) { DBG_Printf(DBG_INFO, "\t06 LQI (?) %lld (0x%010llX)\n", u64, u64); } @@ -10320,6 +10407,7 @@ void DeRestPluginPrivate::handleZclAttributeReportIndicationXiaomiSpecial(const lift = 100 - u8; } DBG_Printf(DBG_INFO, "\t64 lift %d (%d%%)\n", u8, lift); + DBG_Printf(DBG_INFO, "\t64 somke/gas density %d (%d%%)\n", u8); // lumi.sensor_smoke/lumi.sensor_natgas } else if (tag == 0x64 && dataType == deCONZ::Zcl16BitInt) { @@ -10356,6 +10444,10 @@ void DeRestPluginPrivate::handleZclAttributeReportIndicationXiaomiSpecial(const { DBG_Printf(DBG_INFO, "\t6f unknown %d (0x%02X)\n", u8, u8); } + else if (tag == 0x94 && dataType == deCONZ::Zcl8BitUint) // lumi.relay.c2acn01 + { + DBG_Printf(DBG_INFO, "\t6f unknown %d (0x%02X)\n", u8, u8); + } else if (tag == 0x95 && dataType == deCONZ::ZclSingleFloat) // lumi.ctrl_ln2 { consumption = static_cast(round(f * 1000)); // convert to Wh @@ -10366,6 +10458,10 @@ void DeRestPluginPrivate::handleZclAttributeReportIndicationXiaomiSpecial(const voltage = static_cast(round(f / 10)); // convert to V DBG_Printf(DBG_INFO, "\t96 voltage %f (%d)\n", f, voltage); } + else if (tag == 0x96 && dataType == deCONZ::Zcl32BitUint) // lumi.sensor_smoke + { + DBG_Printf(DBG_INFO, "\t96 unknown %d (0x%08X)\n", u32, u32); + } else if (tag == 0x97 && dataType == deCONZ::Zcl16BitUint) // lumi.sensor_cube { DBG_Printf(DBG_INFO, "\t97 unknown %d (0x%04X)\n", u16, u16); @@ -10410,7 +10506,15 @@ void DeRestPluginPrivate::handleZclAttributeReportIndicationXiaomiSpecial(const } else if (tag == 0x9b && dataType == deCONZ::ZclBoolean) // lumi.plug.mmeu01 { - DBG_Printf(DBG_INFO, "\t9b unknown %d\n", u8); + DBG_Printf(DBG_INFO, "\t9b Consumer connected (yes/no) %d\n", u8); + } + else if (structIndex == 0x05 && dataType == deCONZ::Zcl16BitUint) // lumi.sensor_magnet + { + DBG_Printf(DBG_INFO, "\tStruct index 05 unknown (counter?) %d (0x%04X)\n", u16, u16); + } + else if (structIndex == 0x06 && dataType == deCONZ::Zcl8BitUint) // lumi.sensor_magnet + { + DBG_Printf(DBG_INFO, "\tStruct index 06 unknown (counter?) %d (0x%02X)\n", u8, u8); } else if (tag) { diff --git a/de_web_plugin_private.h b/de_web_plugin_private.h index f451dc9439..4d5e2d50df 100644 --- a/de_web_plugin_private.h +++ b/de_web_plugin_private.h @@ -305,6 +305,7 @@ #define VENDOR_SENGLED_OPTOELEC 0x1160 #define VENDOR_INNR 0x1166 #define VENDOR_LDS 0x1168 // Used by Samsung SmartPlug 2019 +#define VENDOR_PLUGWISE_BV 0x1172 #define VENDOR_INSTA 0x117A #define VENDOR_IKEA 0x117C #define VENDOR_3A_SMART_HOME 0x117E @@ -322,6 +323,7 @@ #define VENDOR_DSR 0x1234 #define VENDOR_HANGZHOU_IMAGIC 0x123B #define VENDOR_SAMJIN 0x1241 +#define VENDOR_NIKO_NV 0x125F #define VENDOR_KONKE 0x1268 #define VENDOR_OSRAM_STACK 0xBBAA #define VENDOR_C2DF 0xC2DF @@ -422,6 +424,8 @@ extern const quint64 silabsMacPrefix; extern const quint64 silabs2MacPrefix; extern const quint64 silabs3MacPrefix; extern const quint64 silabs4MacPrefix; +extern const quint64 silabs5MacPrefix; +extern const quint64 silabs6MacPrefix; extern const quint64 instaMacPrefix; extern const quint64 boschMacPrefix; extern const quint64 jennicMacPrefix; @@ -459,7 +463,8 @@ inline bool checkMacVendor(quint64 addr, quint16 vendor) prefix == jennicMacPrefix; case VENDOR_SUNRICHER: return prefix == emberMacPrefix || - prefix == silabs2MacPrefix; + prefix == silabs3MacPrefix || + prefix == silabs6MacPrefix; case VENDOR_ALERTME: return prefix == tiMacPrefix; case VENDOR_BITRON: @@ -474,7 +479,8 @@ inline bool checkMacVendor(quint64 addr, quint16 vendor) case VENDOR_EMBER: return prefix == emberMacPrefix || prefix == konkeMacPrefix || - prefix == silabs3MacPrefix; + prefix == silabs3MacPrefix || + prefix == silabs5MacPrefix; case VENDOR_EMBERTEC: return prefix == embertecMacPrefix; case VENDOR_DDEL: @@ -506,6 +512,8 @@ inline bool checkMacVendor(quint64 addr, quint16 vendor) return prefix == emberMacPrefix; case VENDOR_LUTRON: return prefix == lutronMacPrefix; + case VENDOR_NIKO_BV: + return prefix == konkeMacPrefix; case VENDOR_NYCE: return prefix == emberMacPrefix; case VENDOR_OSRAM: @@ -514,6 +522,8 @@ inline bool checkMacVendor(quint64 addr, quint16 vendor) prefix == heimanMacPrefix; case VENDOR_PHILIPS: return prefix == philipsMacPrefix; + case VENDOR_PLUGWISE_BV: + return prefix == emberMacPrefix; case VENDOR_PHYSICAL: return prefix == stMacPrefix; case VENDOR_SENGLED_OPTOELEC: diff --git a/general.xml b/general.xml index 064e818614..f2480ea04c 100644 --- a/general.xml +++ b/general.xml @@ -1001,7 +1001,7 @@ - + @@ -2439,10 +2439,14 @@ controller device, that supports a keypad and LCD screen. - + + + + + @@ -3337,13 +3341,13 @@ Fil pilote > Off=0001 - On=0002 - + - + - + - + @@ -3381,6 +3385,49 @@ Fil pilote > Off=0001 - On=0002 + + + + Niko specific attributes. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/group.cpp b/group.cpp index e1948455bf..a4854ad0b2 100644 --- a/group.cpp +++ b/group.cpp @@ -31,6 +31,7 @@ Group::Group() : colorY = 0; colorTemperature = 0; colormode = QLatin1String("hs"); + alert = QLatin1String("none"); // add common items addItem(DataTypeString, RAttrName); diff --git a/group.h b/group.h index 99823b5ddd..1edf406929 100644 --- a/group.h +++ b/group.h @@ -65,6 +65,7 @@ class Group : public Resource uint16_t colorTemperature; QString etag; QString colormode; + QString alert; std::vector scenes; QTime sendTime; bool hidden; diff --git a/rest_groups.cpp b/rest_groups.cpp index 217952ab42..92c1f47e6d 100644 --- a/rest_groups.cpp +++ b/rest_groups.cpp @@ -1400,6 +1400,7 @@ int DeRestPluginPrivate::setGroupState(const ApiRequest &req, ApiResponse &rsp) return REQ_READY_SEND; } + group->alert = QLatin1String(alert); taskToLocalData(task); if ((task.taskType == TaskIdentify && addTaskIdentify(task, task.identifyTime)) || @@ -1805,6 +1806,7 @@ bool DeRestPluginPrivate::groupToMap(const ApiRequest &req, const Group *group, action["bri"] = (double)group->level; action["sat"] = (double)group->sat; action["ct"] = (double)group->colorTemperature; + action["alert"] = QLatin1String(group->alert); QVariantList xy; double colorX = group->colorX; diff --git a/sensor.cpp b/sensor.cpp index ecc53f081b..4d861861dc 100644 --- a/sensor.cpp +++ b/sensor.cpp @@ -794,6 +794,17 @@ static const Sensor::ButtonMap tintMap[] = { { Sensor::ModeNone, 0x00, 0x0000, 0x00, 0, 0, nullptr } }; +static const Sensor::ButtonMap sageMap[] = { +// mode ep cluster cmd param button name + { Sensor::ModeScenes, 0x12, 0x0006, 0x01, 0, S_BUTTON_1 + S_BUTTON_ACTION_SHORT_RELEASED, "On" }, + { Sensor::ModeScenes, 0x12, 0x0006, 0x00, 0, S_BUTTON_2 + S_BUTTON_ACTION_SHORT_RELEASED, "Off" }, + { Sensor::ModeScenes, 0x12, 0x0008, 0x05, 0, S_BUTTON_3 + S_BUTTON_ACTION_HOLD, "On (hold)" }, + { Sensor::ModeScenes, 0x12, 0x0008, 0x03, 0, S_BUTTON_3 + S_BUTTON_ACTION_LONG_RELEASED, "On (released)" }, + + // end + { Sensor::ModeNone, 0x00, 0x0000, 0x00, 0, 0, nullptr } +}; + /*! Returns a fingerprint as JSON string. */ QString SensorFingerprint::toString() const { @@ -1347,6 +1358,10 @@ const Sensor::ButtonMap *Sensor::buttonMap() if (modelid.startsWith(QLatin1String("ICZB-KPD1"))) { m_buttonMap = icasaKeypadMap; } else if (modelid.startsWith(QLatin1String("ICZB-RM"))) { m_buttonMap = icasaRemoteMap; } } + else if (manufacturer == QLatin1String("EcoDim")) + { + if (modelid.startsWith(QLatin1String("ED-1001"))) { m_buttonMap = icasaKeypadMap; } + } else if (manufacturer == QLatin1String("Samjin")) { if (modelid == QLatin1String("button")) { m_buttonMap = samjinButtonMap; } @@ -1374,16 +1389,21 @@ const Sensor::ButtonMap *Sensor::buttonMap() } else if (manufacturer == QLatin1String("Namron AS")) { - if (modelid.startsWith(QLatin1String("4512703"))) { m_buttonMap = sunricherMap; } + if (modelid.startsWith(QLatin1String("451270"))) { m_buttonMap = sunricherMap; } } else if (manufacturer == QLatin1String("Heiman")) { if (modelid == QLatin1String("RC_V14")) { m_buttonMap = rcv14Map; } + else if (modelid == QLatin1String("RC-EM")) { m_buttonMap = rcv14Map; } } else if (manufacturer == QLatin1String("MLI")) { if (modelid.startsWith(QLatin1String("ZBT-Remote-ALL-RGBW"))) { m_buttonMap = tintMap; } } + else if (manufacturer == QLatin1String("Echostar")) + { + if (modelid == QLatin1String("Bell")) { m_buttonMap = sageMap; } + } } return m_buttonMap;