From f4c7e39eb129d40afb9b8172b2ea50687094563c Mon Sep 17 00:00:00 2001 From: ebaauw Date: Sat, 26 Aug 2023 22:43:03 +0200 Subject: [PATCH 01/12] Update constants.json Add `$MF_AQARA` --- devices/generic/constants.json | 1 + 1 file changed, 1 insertion(+) diff --git a/devices/generic/constants.json b/devices/generic/constants.json index 34355747ee..0c41ab8c32 100644 --- a/devices/generic/constants.json +++ b/devices/generic/constants.json @@ -2,6 +2,7 @@ "schema": "constants1.schema.json", "manufacturers" : { + "$MF_AQARA": "Aqara", "$MF_BOSCH": "Bosch", "$MF_IKEA": "IKEA of Sweden", "$MF_LUMI": "LUMI", From 26d25fbe4e1110275a7cb15aa044c659a4b575c2 Mon Sep 17 00:00:00 2001 From: ebaauw Date: Sat, 26 Aug 2023 22:43:15 +0200 Subject: [PATCH 02/12] Create lumi_light_acn132.json --- devices/xiaomi/lumi_light_acn132.json | 168 ++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 devices/xiaomi/lumi_light_acn132.json diff --git a/devices/xiaomi/lumi_light_acn132.json b/devices/xiaomi/lumi_light_acn132.json new file mode 100644 index 0000000000..26cea78711 --- /dev/null +++ b/devices/xiaomi/lumi_light_acn132.json @@ -0,0 +1,168 @@ +{ + "schema": "devcap1.schema.json", + "manufacturername": [ + "$MF_AQARA" + ], + "modelid": [ + "lumi.light.acn132" + ], + "product": "Aqara LED Strip T1", + "sleeper": false, + "status": "Gold", + "subdevices": [ + { + "type": "$TYPE_EXTENDED_COLOR_LIGHT", + "restapi": "/lights", + "uuid": [ + "$address.ext", + "0x01" + ], + "items": [ + { + "name": "attr/id" + }, + { + "name": "attr/lastannounced" + }, + { + "name": "attr/lastseen" + }, + { + "name": "attr/manufacturername" + }, + { + "name": "attr/modelid" + }, + { + "name": "attr/name" + }, + { + "name": "attr/swversion", + "parse": { + "fn": "xiaomi:special", + "mf": "0x115F", + "at": "0x00F7", + "idx": "0x0D", + "eval": "Item.val = '0.0.0_' + ('0000' + (Attr.val & 0xFFFF).toString()).slice(-4)" + }, + "read": { + "fn": "none" + } + }, + { + "name": "attr/type" + }, + { + "name": "attr/uniqueid" + }, + { + "name": "cap/bri/move_with_onoff" + }, + { + "name": "cap/color/capabilities", + "read": { + "fn": "zcl", "ep": "0x01", "cl": "0x0300", "at": ["0x400a", "0x400b", "0x400c", "0x000f"] + }, + "refresh.interval": 86400 + }, + { + "name": "cap/color/ct/max" + }, + { + "name": "cap/color/ct/min" + }, + { + "name": "cap/color/ct/computes_xy" + }, + { + "name": "cap/color/xy/blue_x", + "static": 0 + }, + { + "name": "cap/color/xy/blue_y", + "static": 0 + }, + { + "name": "cap/color/xy/green_x", + "static": 0 + }, + { + "name": "cap/color/xy/green_y", + "static": 65279 + }, + { + "name": "cap/color/xy/red_x", + "static": 65279 + }, + { + "name": "cap/color/xy/red_y", + "static": 0 + }, + { + "name": "config/bri/execute_if_off", + "read": { + "fn": "zcl", "ep": "0x01", "cl": "0x0008", "at": ["0x000f", "0x0010", "0x0011", "0x4000"] + }, + "refresh.interval": 86400 + }, + { + "name": "config/bri/on_level", + "read": { "fn": "none" } + }, + { + "name": "config/bri/onoff_transitiontime", + "read": { "fn": "none" } + }, + { + "name": "config/color/execute_if_off", + "read": { "fn": "none" } + }, + { + "name": "config/on/startup", + "read": { "fn": "none" } + }, + { + "name": "state/alert" + }, + { + "name": "state/on", + "refresh.interval": 365 + }, + { + "name": "state/bri", + "refresh.interval": 365 + }, + { + "name": "state/colormode", + "parse": { + "fn": "zcl", "ep": "0x01", "cl": "0x0300", "at": "0x4001", + "eval": "Item.val = ['hs', 'xy', 'ct', 'xy'][Attr.val]" + }, + "read": { + "fn": "zcl", "ep": "0x01", "cl": "0x0300", "at": ["0x4001", "0x0003", "0x0004", "0x0007"] + }, + "refresh.interval": 365 + }, + { + "name": "state/x", + "read": { "fn": "none" } + }, + { + "name": "state/y", + "read": { "fn": "none" } + }, + { + "name": "state/ct", + "read": { "fn": "none" } + }, + { + "name": "state/effect", + "read": { "fn": "none" } + }, + { + "name": "state/reachable" + } + ] + } + ] +} From 65fdf109604ea9a8d7cdd7236e477a7073b36742 Mon Sep 17 00:00:00 2001 From: ebaauw Date: Sat, 26 Aug 2023 23:04:43 +0200 Subject: [PATCH 03/12] Update lumi_light_acn132.json Fix attr/swversion --- devices/xiaomi/lumi_light_acn132.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devices/xiaomi/lumi_light_acn132.json b/devices/xiaomi/lumi_light_acn132.json index 26cea78711..c0cf8a9e66 100644 --- a/devices/xiaomi/lumi_light_acn132.json +++ b/devices/xiaomi/lumi_light_acn132.json @@ -43,7 +43,7 @@ "mf": "0x115F", "at": "0x00F7", "idx": "0x0D", - "eval": "Item.val = '0.0.0_' + ('0000' + (Attr.val & 0xFFFF).toString()).slice(-4)" + "eval": "Item.val = '0.0.0_' + ('0000' + ((Attr.val & 0xFF00) >> 8).toString() + (Attr.val & 0xFF).toString()).slice(-4)" }, "read": { "fn": "none" From 9a6a0927b6676571bd03f02dd14e9e1ec080a907 Mon Sep 17 00:00:00 2001 From: ebaauw Date: Sun, 27 Aug 2023 00:41:39 +0200 Subject: [PATCH 04/12] Update general.xml Additional attributes for Aqara LED Strip T1. --- general.xml | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/general.xml b/general.xml index 0db4d8c82a..8b275ac399 100644 --- a/general.xml +++ b/general.xml @@ -5542,7 +5542,7 @@ Contactor > On/off=0003 - HP/HC=0004 - + @@ -5596,7 +5596,7 @@ Contactor > On/off=0003 - HP/HC=0004 - + Write 1 to calibrate @@ -5648,7 +5648,26 @@ Contactor > On/off=0003 - HP/HC=0004 - + + + + + OnOff state on power on: 0: on, 1: previous, 2: off. + + + Number of 20cm segments. + + + Music Sync: 0: off, 1: on. + + + Music Sync Effecy: 0: random, 1: breathing, 2: rainbow, 3: chasing. + + + Music Sync Sensitivity: 0: low, 2: high. + + + From b320058af1255ed06b038818c0642b27a2117f17 Mon Sep 17 00:00:00 2001 From: ebaauw Date: Sun, 27 Aug 2023 00:42:17 +0200 Subject: [PATCH 05/12] Update lumi_light_acn132.json --- devices/xiaomi/lumi_light_acn132.json | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/devices/xiaomi/lumi_light_acn132.json b/devices/xiaomi/lumi_light_acn132.json index c0cf8a9e66..97681d0056 100644 --- a/devices/xiaomi/lumi_light_acn132.json +++ b/devices/xiaomi/lumi_light_acn132.json @@ -61,7 +61,7 @@ { "name": "cap/color/capabilities", "read": { - "fn": "zcl", "ep": "0x01", "cl": "0x0300", "at": ["0x400a", "0x400b", "0x400c", "0x000f"] + "fn": "zcl:attr", "ep": "0x01", "cl": "0x0300", "at": ["0x400a", "0x400b", "0x400c", "0x000f"] }, "refresh.interval": 86400 }, @@ -101,7 +101,7 @@ { "name": "config/bri/execute_if_off", "read": { - "fn": "zcl", "ep": "0x01", "cl": "0x0008", "at": ["0x000f", "0x0010", "0x0011", "0x4000"] + "fn": "zcl:attr", "ep": "0x01", "cl": "0x0008", "at": ["0x000f", "0x0010", "0x0011"] }, "refresh.interval": 86400 }, @@ -119,7 +119,15 @@ }, { "name": "config/on/startup", - "read": { "fn": "none" } + "parse": { + "fn": "zcl:attr", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": "0x0517", + "eval": "Item.val = [1, 255, 0][Attr.val]" + }, + "read": { "fn": "zcl:attr", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": ["0x0517"] }, + "write": { + "fn": "zcl:attr", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": "0x0517", "dt": "0x20", + "eval": "Item.val === 1 ? 0 : Item.val === 0 ? 2 : 1" + } }, { "name": "state/alert" @@ -135,11 +143,11 @@ { "name": "state/colormode", "parse": { - "fn": "zcl", "ep": "0x01", "cl": "0x0300", "at": "0x4001", + "fn": "zcl:attr", "ep": "0x01", "cl": "0x0300", "at": "0x4001", "eval": "Item.val = ['hs', 'xy', 'ct', 'xy'][Attr.val]" }, "read": { - "fn": "zcl", "ep": "0x01", "cl": "0x0300", "at": ["0x4001", "0x0003", "0x0004", "0x0007"] + "fn": "zcl:attr", "ep": "0x01", "cl": "0x0300", "at": ["0x4001", "0x0003", "0x0004", "0x0007"] }, "refresh.interval": 365 }, @@ -155,10 +163,6 @@ "name": "state/ct", "read": { "fn": "none" } }, - { - "name": "state/effect", - "read": { "fn": "none" } - }, { "name": "state/reachable" } From 0461a41099f1ae15753b721ffa4809283665142e Mon Sep 17 00:00:00 2001 From: ebaauw Date: Sun, 27 Aug 2023 16:15:14 +0200 Subject: [PATCH 06/12] Add resource items for Aqara LED Strip T1 --- devices/generic/items/attr_swversion_bis_item.json | 9 +++++++++ .../items/config_color_gradient_pixel_count_item.json | 8 ++++++++ devices/generic/items/state_music_sync_item.json | 8 ++++++++ resource.cpp | 6 ++++++ resource.h | 3 +++ 5 files changed, 34 insertions(+) create mode 100644 devices/generic/items/attr_swversion_bis_item.json create mode 100644 devices/generic/items/config_color_gradient_pixel_count_item.json create mode 100644 devices/generic/items/state_music_sync_item.json diff --git a/devices/generic/items/attr_swversion_bis_item.json b/devices/generic/items/attr_swversion_bis_item.json new file mode 100644 index 0000000000..ab448efa12 --- /dev/null +++ b/devices/generic/items/attr_swversion_bis_item.json @@ -0,0 +1,9 @@ +{ + "schema": "resourceitem1.schema.json", + "id": "attr/swversion_bis", + "datatype": "String", + "access": "R", + "public": true, + "implicit" : true, + "description": "Firmware version of the device." +} diff --git a/devices/generic/items/config_color_gradient_pixel_count_item.json b/devices/generic/items/config_color_gradient_pixel_count_item.json new file mode 100644 index 0000000000..5c1f70e9f7 --- /dev/null +++ b/devices/generic/items/config_color_gradient_pixel_count_item.json @@ -0,0 +1,8 @@ +{ + "schema": "resourceitem1.schema.json", + "id": "config/color/gradient/pixel_count", + "datatype": "UInt8", + "access": "RW", + "public": true, + "description": "Number of pixels on Aqara LED Strip T1." +} diff --git a/devices/generic/items/state_music_sync_item.json b/devices/generic/items/state_music_sync_item.json new file mode 100644 index 0000000000..0aae9508c6 --- /dev/null +++ b/devices/generic/items/state_music_sync_item.json @@ -0,0 +1,8 @@ +{ + "schema": "resourceitem1.schema.json", + "id": "state/music_sync", + "datatype": "Bool", + "access": "RW", + "public": true, + "description": "Music sync on or off." +} diff --git a/resource.cpp b/resource.cpp index 69230ba9ed..e4c8c23a18 100644 --- a/resource.cpp +++ b/resource.cpp @@ -74,6 +74,7 @@ const char *RAttrProductId = "attr/productid"; const char *RAttrProductName = "attr/productname"; const char *RAttrSwconfigid = "attr/swconfigid"; const char *RAttrSwVersion = "attr/swversion"; +const char *RAttrSwVersionBis = "attr/swversion_bis"; const char *RAttrType = "attr/type"; const char *RAttrUniqueId = "attr/uniqueid"; @@ -134,6 +135,7 @@ const char *RStateLowBattery = "state/lowbattery"; const char *RStateLux = "state/lux"; const char *RStateMoisture = "state/moisture"; const char *RStateMountingModeActive = "state/mountingmodeactive"; +const char *RStateMusicSync = "state/music_sync"; const char *RStateOn = "state/on"; const char *RStateOpen = "state/open"; const char *RStateOpenBis = "state/open_bis"; @@ -242,6 +244,7 @@ const char *RConfigClickMode = "config/clickmode"; const char *RConfigColorCapabilities = "config/colorcapabilities"; const char *RConfigColorCtStartup = "config/color/ct/startup"; const char *RConfigColorExecuteIfOff = "config/color/execute_if_off"; +const char *RConfigColorGradientPixelCount = "config/color/gradient/pixel_count"; const char *RConfigColorGradientReversed = "config/color/gradient/reversed"; const char *RConfigColorXyStartupX = "config/color/xy/startup_x"; const char *RConfigColorXyStartupY = "config/color/xy/startup_y"; @@ -374,6 +377,7 @@ void initResourceDescriptors() rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeString, QVariant::String, RAttrProductName)); rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeString, QVariant::String, RAttrSwconfigid)); rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeString, QVariant::String, RAttrSwVersion)); + rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeString, QVariant::String, RAttrSwVersionBis)); rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeString, QVariant::String, RAttrType)); rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeString, QVariant::String, RAttrUniqueId)); @@ -435,6 +439,7 @@ void initResourceDescriptors() rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeUInt32, QVariant::Double, RStateLux)); rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeInt16, QVariant::Double, RStateMoisture)); rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeBool, QVariant::Bool, RStateMountingModeActive)); + rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeBool, QVariant::Bool, RStateMusicSync)); rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeBool, QVariant::Bool, RStateOn)); rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeBool, QVariant::Bool, RStateOpen)); rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeBool, QVariant::Bool, RStateOpenBis)); @@ -529,6 +534,7 @@ void initResourceDescriptors() rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeUInt16, QVariant::Double, RConfigColorCapabilities)); rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeUInt16, QVariant::Double, RConfigColorCtStartup)); rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeBool, QVariant::Bool, RConfigColorExecuteIfOff)); + rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeUInt8, QVariant::Double, RConfigColorGradientPixelCount, 5, 50)); rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeBool, QVariant::Bool, RConfigColorGradientReversed)); rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeUInt16, QVariant::Double, RConfigColorXyStartupX)); rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeUInt16, QVariant::Double, RConfigColorXyStartupY)); diff --git a/resource.h b/resource.h index a5b658bbd6..bd44d4f952 100644 --- a/resource.h +++ b/resource.h @@ -103,6 +103,7 @@ extern const char *RAttrProductId; extern const char *RAttrProductName; extern const char *RAttrSwconfigid; extern const char *RAttrSwVersion; +extern const char *RAttrSwVersionBis; extern const char *RAttrType; extern const char *RAttrUniqueId; @@ -163,6 +164,7 @@ extern const char *RStateLowBattery; extern const char *RStateLux; extern const char *RStateMoisture; extern const char *RStateMountingModeActive; +extern const char *RStateMusicSync; extern const char *RStateOn; extern const char *RStateOpen; extern const char *RStateOpenBis; @@ -256,6 +258,7 @@ extern const char *RConfigClickMode; extern const char *RConfigColorCapabilities; // Deprecated extern const char *RConfigColorCtStartup; extern const char *RConfigColorExecuteIfOff; +extern const char *RConfigColorGradientPixelCount; extern const char *RConfigColorGradientReversed; extern const char *RConfigColorXyStartupX; extern const char *RConfigColorXyStartupY; From 23ebe9bc8fd938d3afb6403a0e83388b40009a5e Mon Sep 17 00:00:00 2001 From: ebaauw Date: Sun, 27 Aug 2023 16:15:43 +0200 Subject: [PATCH 07/12] Update rest_lights.cpp Add support for Aqara LED Strip T1 --- rest_lights.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/rest_lights.cpp b/rest_lights.cpp index 3e99f4f4df..5b5127ef47 100644 --- a/rest_lights.cpp +++ b/rest_lights.cpp @@ -319,6 +319,7 @@ bool DeRestPluginPrivate::lightToMap(const ApiRequest &req, const LightNode *lig else if (rid.suffix == RConfigBriStartup) { configBri["startup"] = item->toNumber() == 0xFF ? QVariant(QLatin1String("previous")) : item->toNumber(); } else if (rid.suffix == RConfigColorCtStartup) { configColorCt["startup"] = item->toNumber() == 0xFFFF ? QVariant(QLatin1String("previous")) : item->toNumber(); } else if (rid.suffix == RConfigColorExecuteIfOff) { configColor["execute_if_off"] = item->toBool(); } + else if (rid.suffix == RConfigColorGradientPixelCount) { configColorGradient["pixel_count"] = item->toNumber(); } else if (rid.suffix == RConfigColorGradientReversed) { configColorGradient["reversed"] = item->toBool(); } else if (rid.suffix == RConfigColorXyStartupX) { isx = item; } else if (rid.suffix == RConfigColorXyStartupY) { isy = item; } @@ -345,6 +346,7 @@ bool DeRestPluginPrivate::lightToMap(const ApiRequest &req, const LightNode *lig else if (rid.suffix == RStateLift) { state["lift"] = item->toNumber(); } else if (rid.suffix == RStateOn) { state["on"] = item->toBool(); } else if (rid.suffix == RStateOpen) { state["open"] = item->toBool(); } + else if (rid.suffix == RStateMusicSync) { state["music_sync"] = item->toBool(); } else if (rid.suffix == RStateReachable) { state["reachable"] = item->toBool(); } else if (rid.suffix == RStateSat) { state["sat"] = item->toNumber(); } else if (rid.suffix == RStateSpeed) { state["speed"] = item->toNumber(); } @@ -647,6 +649,12 @@ int DeRestPluginPrivate::setLightState(const ApiRequest &req, ApiResponse &rsp) } Device *device = static_cast(taskRef.lightNode->parentResource()); + Resource *rsub = nullptr; + StateChange change(StateChange::StateCallFunction, SC_WriteZclAttribute, taskRef.lightNode->haEndpoint().endpoint()); + if (device && device->managed()) + { + rsub = DEV_GetSubDevice(device, nullptr, taskRef.lightNode->uniqueId()); + } rsp.httpStatus = HttpStatusOk; if (!taskRef.lightNode->isAvailable()) @@ -753,6 +761,8 @@ int DeRestPluginPrivate::setLightState(const ApiRequest &req, ApiResponse &rsp) quint16 colorloopSpeed = 25; bool hasGradient = false; QVariantMap gradient; + bool hasMusicSync = false; + bool targetMusicSync = false; QString alert; bool hasSpeed = false; quint8 targetSpeed = 0; @@ -906,6 +916,17 @@ int DeRestPluginPrivate::setLightState(const ApiRequest &req, ApiResponse &rsp) valueOk = effect >= 0; } } + else if (param == "music_sync" && taskRef.lightNode->item(RStateMusicSync)) + { + paramOk = true; + hasCmd = true; + if (map[param].type() == QVariant::Bool) + { + valueOk = true; + hasMusicSync = true; + targetMusicSync = map[param].toBool(); + } + } else if (param == "colorloopspeed" && taskRef.lightNode->item(RStateEffect)) { paramOk = true; @@ -1464,6 +1485,19 @@ int DeRestPluginPrivate::setLightState(const ApiRequest &req, ApiResponse &rsp) } } + if (hasMusicSync) + { + change.addTargetValue(RStateMusicSync, targetMusicSync); + taskRef.lightNode->setValue(RStateMusicSync, targetMusicSync); + DB_StoreSubDeviceItem(taskRef.lightNode, taskRef.lightNode->item(RStateMusicSync)); + + QVariantMap rspItem; + QVariantMap rspItemState; + rspItemState[QString("/lights/%1/state/music_sync").arg(id)] = targetMusicSync; + rspItem["success"] = rspItemState; + rsp.list.append(rspItem); + } + // state.alert if (!alert.isEmpty()) { @@ -1604,6 +1638,10 @@ int DeRestPluginPrivate::setLightState(const ApiRequest &req, ApiResponse &rsp) } rsp.etag = taskRef.lightNode->etag; + if (rsub) + { + rsub->addStateChange(change); + } processTasks(); return REQ_READY_SEND; } @@ -1965,7 +2003,27 @@ int DeRestPluginPrivate::setLightConfig(const ApiRequest &req, ApiResponse &rsp) QString path2 = QString("%1/%2").arg(path1).arg(key); value = map2[key]; - if (key == "reversed") + if (key == "pixel_count") + { + ResourceItem *item = lightNode->item(RConfigColorGradientPixelCount); + if (item) + { + paramOk = true; + if (value.type() == QVariant::Double) + { + const quint8 pixelCount = value.toUInt(&ok); + if (ok) + { + valueOk = true; + change.addTargetValue(RConfigColorGradientPixelCount, pixelCount); + lightNode->setValue(RConfigColorGradientPixelCount, pixelCount); + DB_StoreSubDeviceItem(lightNode, item); + } + } + } + + } + else if (key == "reversed") { ResourceItem *item = lightNode->item(RConfigColorGradientReversed); if (item) @@ -3848,6 +3906,7 @@ void DeRestPluginPrivate::handleLightEvent(const Event &e) else if (rid.suffix == RConfigBriStartup) { configBri["startup"] = item->toNumber() == 0xFF ? QVariant(QLatin1String("previous")) : item->toNumber(); } else if (rid.suffix == RConfigColorCtStartup) { configColorCt["startup"] = item->toNumber() == 0xFFFF ? QVariant(QLatin1String("previous")) : item->toNumber(); } else if (rid.suffix == RConfigColorExecuteIfOff) { configColor["execute_if_off"] = item->toBool(); } + else if (rid.suffix == RConfigColorGradientPixelCount) { configColorGradient["pixel_count"] = item->toNumber(); } else if (rid.suffix == RConfigColorGradientReversed) { configColorGradient["reversed"] = item->toBool(); } else if (rid.suffix == RConfigLocked) { config["locked"] = item->toBool(); } else if (rid.suffix == RConfigOnStartup) { configOn["startup"] = item->toNumber() == 0xFF ? QVariant(QLatin1String("previous")) : item->toBool(); } @@ -3871,6 +3930,7 @@ void DeRestPluginPrivate::handleLightEvent(const Event &e) else if (rid.suffix == RStateLift) { state["lift"] = item->toNumber(); } else if (rid.suffix == RStateOn) { state["on"] = item->toBool(); } else if (rid.suffix == RStateOpen) { state["open"] = item->toBool(); } + else if (rid.suffix == RStateMusicSync) { state["music_sync"] = item->toBool(); } else if (rid.suffix == RStateReachable) { state["reachable"] = item->toBool(); } else if (rid.suffix == RStateSat) { state["sat"] = item->toNumber(); } else if (rid.suffix == RStateSpeed) { state["speed"] = item->toNumber(); } From 2f08b3f88c08062b206b1a85126731d8e6a5daf9 Mon Sep 17 00:00:00 2001 From: ebaauw Date: Sun, 27 Aug 2023 16:15:53 +0200 Subject: [PATCH 08/12] Update lumi_light_acn132.json --- devices/xiaomi/lumi_light_acn132.json | 74 ++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/devices/xiaomi/lumi_light_acn132.json b/devices/xiaomi/lumi_light_acn132.json index 97681d0056..2ea52cff6e 100644 --- a/devices/xiaomi/lumi_light_acn132.json +++ b/devices/xiaomi/lumi_light_acn132.json @@ -38,12 +38,23 @@ }, { "name": "attr/swversion", + "parse": { + "fn": "zcl:attr", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": "0x00EE", + "eval": "Item.val = '0.0.0_' + ('0000' + ((Attr.val & 0xFF00) >> 8).toString() + (Attr.val & 0xFF).toString()).slice(-4)" + }, + "read": { + "fn": "zcl", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": ["0x00EE"] + }, + "refresh.interval": 86400 + }, + { + "name": "attr/swversion_bis", "parse": { "fn": "xiaomi:special", "mf": "0x115F", "at": "0x00F7", "idx": "0x0D", - "eval": "Item.val = '0.0.0_' + ('0000' + ((Attr.val & 0xFF00) >> 8).toString() + (Attr.val & 0xFF).toString()).slice(-4)" + "eval": "R.item('attr/swversion').val = '0.0.0_' + ('0000' + ((Attr.val & 0xFF00) >> 8).toString() + (Attr.val & 0xFF).toString()).slice(-4)" }, "read": { "fn": "none" @@ -74,6 +85,10 @@ { "name": "cap/color/ct/computes_xy" }, + { + "name": "cap/color/gradient/pixel_length", + "static": 2000 + }, { "name": "cap/color/xy/blue_x", "static": 0 @@ -105,6 +120,33 @@ }, "refresh.interval": 86400 }, + { + "name": "config/bri/max", + "parse": { + "fn": "zcl", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": "0x0516", + "eval": "Item.val = Math.round(Attr.val * 2.54)" + }, + "read": { + "fn": "zcl", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": ["0x0516", "0x0515"] + }, + "refresh.interval": 3600, + "write": { + "fn": "zcl", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": "0x0516", "dt": "0x20", + "eval": "Math.round(Item.val / 2.54)" + } + }, + { + "name": "config/bri/min", + "parse": { + "fn": "zcl", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": "0x0515", + "eval": "Item.val = Math.round(Attr.val * 2.54)" + }, + "read": { "fn": "none" }, + "write": { + "fn": "zcl", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": "0x0515", "dt": "0x20", + "eval": "Math.round(Item.val / 2.54)" + } + }, { "name": "config/bri/on_level", "read": { "fn": "none" } @@ -117,6 +159,21 @@ "name": "config/color/execute_if_off", "read": { "fn": "none" } }, + { + "name": "config/color/gradient/pixel_count", + "parse": { + "fn": "zcl:attr", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": "0x051B", + "eval": "Item.val = Attr.val" + }, + "read": { + "fn": "zcl", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": ["0x051B"] + }, + "refresh.interval": 86400, + "write": { + "fn": "zcl:attr", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": "0x051B", + "eval": "Math.max(5, Math.min(Attr.val, 50))" + } + }, { "name": "config/on/startup", "parse": { @@ -151,6 +208,21 @@ }, "refresh.interval": 365 }, + { + "name": "state/music_sync", + "parse": { + "fn": "zcl", "ep": 0, "cl": "0xFCC0", "mf": "0x115F", "at": "0x051C", + "eval": "Item.val = Attr.val === 1" + }, + "read": { + "fn": "zcl", "ep": 0, "cl": "0xFCC0", "mf": "0x115F", "at": ["0x051C"] + }, + "refresh.interval": 305, + "write": { + "fn": "zcl", "ep": 0, "cl": "0xFCC0", "mf": "0x115F", "at": "0x051C", "dt": "0x20", + "eval": "Item.val ? 1 : 0" + } + }, { "name": "state/x", "read": { "fn": "none" } From 4ef2e56bc11dafcfac72d843fcc0eb7d401c5f66 Mon Sep 17 00:00:00 2001 From: ebaauw Date: Sun, 10 Sep 2023 21:15:33 +0200 Subject: [PATCH 09/12] Update lumi_light_acn132.json - Reformat; - Add missing `dt` to `write` of `config/color/gradient/pixel_count`. --- devices/xiaomi/lumi_light_acn132.json | 180 +++++++++++++++++++++----- 1 file changed, 151 insertions(+), 29 deletions(-) diff --git a/devices/xiaomi/lumi_light_acn132.json b/devices/xiaomi/lumi_light_acn132.json index 2ea52cff6e..d0af0dbb36 100644 --- a/devices/xiaomi/lumi_light_acn132.json +++ b/devices/xiaomi/lumi_light_acn132.json @@ -39,11 +39,21 @@ { "name": "attr/swversion", "parse": { - "fn": "zcl:attr", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": "0x00EE", + "fn": "zcl:attr", + "ep": "0x01", + "cl": "0xFCC0", + "mf": "0x115F", + "at": "0x00EE", "eval": "Item.val = '0.0.0_' + ('0000' + ((Attr.val & 0xFF00) >> 8).toString() + (Attr.val & 0xFF).toString()).slice(-4)" }, "read": { - "fn": "zcl", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": ["0x00EE"] + "fn": "zcl", + "ep": "0x01", + "cl": "0xFCC0", + "mf": "0x115F", + "at": [ + "0x00EE" + ] }, "refresh.interval": 86400 }, @@ -72,7 +82,15 @@ { "name": "cap/color/capabilities", "read": { - "fn": "zcl:attr", "ep": "0x01", "cl": "0x0300", "at": ["0x400a", "0x400b", "0x400c", "0x000f"] + "fn": "zcl:attr", + "ep": "0x01", + "cl": "0x0300", + "at": [ + "0x400a", + "0x400b", + "0x400c", + "0x000f" + ] }, "refresh.interval": 86400 }, @@ -116,78 +134,150 @@ { "name": "config/bri/execute_if_off", "read": { - "fn": "zcl:attr", "ep": "0x01", "cl": "0x0008", "at": ["0x000f", "0x0010", "0x0011"] + "fn": "zcl:attr", + "ep": "0x01", + "cl": "0x0008", + "at": [ + "0x000f", + "0x0010", + "0x0011" + ] }, "refresh.interval": 86400 }, { "name": "config/bri/max", "parse": { - "fn": "zcl", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": "0x0516", + "fn": "zcl", + "ep": "0x01", + "cl": "0xFCC0", + "mf": "0x115F", + "at": "0x0516", "eval": "Item.val = Math.round(Attr.val * 2.54)" }, "read": { - "fn": "zcl", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": ["0x0516", "0x0515"] + "fn": "zcl", + "ep": "0x01", + "cl": "0xFCC0", + "mf": "0x115F", + "at": [ + "0x0516", + "0x0515" + ] }, "refresh.interval": 3600, "write": { - "fn": "zcl", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": "0x0516", "dt": "0x20", + "fn": "zcl", + "ep": "0x01", + "cl": "0xFCC0", + "mf": "0x115F", + "at": "0x0516", + "dt": "0x20", "eval": "Math.round(Item.val / 2.54)" } }, { "name": "config/bri/min", "parse": { - "fn": "zcl", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": "0x0515", + "fn": "zcl", + "ep": "0x01", + "cl": "0xFCC0", + "mf": "0x115F", + "at": "0x0515", "eval": "Item.val = Math.round(Attr.val * 2.54)" }, - "read": { "fn": "none" }, + "read": { + "fn": "none" + }, "write": { - "fn": "zcl", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": "0x0515", "dt": "0x20", + "fn": "zcl", + "ep": "0x01", + "cl": "0xFCC0", + "mf": "0x115F", + "at": "0x0515", + "dt": "0x20", "eval": "Math.round(Item.val / 2.54)" } }, { "name": "config/bri/on_level", - "read": { "fn": "none" } + "read": { + "fn": "none" + } }, { "name": "config/bri/onoff_transitiontime", - "read": { "fn": "none" } + "read": { + "fn": "none" + } }, { "name": "config/color/execute_if_off", - "read": { "fn": "none" } + "read": { + "fn": "none" + } }, { "name": "config/color/gradient/pixel_count", "parse": { - "fn": "zcl:attr", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": "0x051B", + "fn": "zcl:attr", + "ep": "0x01", + "cl": "0xFCC0", + "mf": "0x115F", + "at": "0x051B", "eval": "Item.val = Attr.val" }, "read": { - "fn": "zcl", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": ["0x051B"] + "fn": "zcl", + "ep": "0x01", + "cl": "0xFCC0", + "mf": "0x115F", + "at": [ + "0x051B" + ] }, "refresh.interval": 86400, "write": { - "fn": "zcl:attr", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": "0x051B", + "fn": "zcl:attr", + "ep": "0x01", + "cl": "0xFCC0", + "mf": "0x115F", + "at": "0x051B", + "dt": "0x20", "eval": "Math.max(5, Math.min(Attr.val, 50))" } }, { "name": "config/on/startup", "parse": { - "fn": "zcl:attr", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": "0x0517", + "fn": "zcl:attr", + "ep": "0x01", + "cl": "0xFCC0", + "mf": "0x115F", + "at": "0x0517", "eval": "Item.val = [1, 255, 0][Attr.val]" }, - "read": { "fn": "zcl:attr", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": ["0x0517"] }, + "read": { + "fn": "zcl:attr", + "ep": "0x01", + "cl": "0xFCC0", + "mf": "0x115F", + "at": [ + "0x0517" + ] + }, "write": { - "fn": "zcl:attr", "ep": "0x01", "cl": "0xFCC0", "mf": "0x115F", "at": "0x0517", "dt": "0x20", + "fn": "zcl:attr", + "ep": "0x01", + "cl": "0xFCC0", + "mf": "0x115F", + "at": "0x0517", + "dt": "0x20", "eval": "Item.val === 1 ? 0 : Item.val === 0 ? 2 : 1" } }, { - "name": "state/alert" + "name": "state/alert" }, { "name": "state/on", @@ -200,40 +290,72 @@ { "name": "state/colormode", "parse": { - "fn": "zcl:attr", "ep": "0x01", "cl": "0x0300", "at": "0x4001", + "fn": "zcl:attr", + "ep": "0x01", + "cl": "0x0300", + "at": "0x4001", "eval": "Item.val = ['hs', 'xy', 'ct', 'xy'][Attr.val]" }, "read": { - "fn": "zcl:attr", "ep": "0x01", "cl": "0x0300", "at": ["0x4001", "0x0003", "0x0004", "0x0007"] + "fn": "zcl:attr", + "ep": "0x01", + "cl": "0x0300", + "at": [ + "0x4001", + "0x0003", + "0x0004", + "0x0007" + ] }, "refresh.interval": 365 }, { "name": "state/music_sync", - "parse": { - "fn": "zcl", "ep": 0, "cl": "0xFCC0", "mf": "0x115F", "at": "0x051C", + "parse": { + "fn": "zcl", + "ep": 0, + "cl": "0xFCC0", + "mf": "0x115F", + "at": "0x051C", "eval": "Item.val = Attr.val === 1" }, "read": { - "fn": "zcl", "ep": 0, "cl": "0xFCC0", "mf": "0x115F", "at": ["0x051C"] + "fn": "zcl", + "ep": 0, + "cl": "0xFCC0", + "mf": "0x115F", + "at": [ + "0x051C" + ] }, "refresh.interval": 305, "write": { - "fn": "zcl", "ep": 0, "cl": "0xFCC0", "mf": "0x115F", "at": "0x051C", "dt": "0x20", + "fn": "zcl", + "ep": 0, + "cl": "0xFCC0", + "mf": "0x115F", + "at": "0x051C", + "dt": "0x20", "eval": "Item.val ? 1 : 0" } }, { "name": "state/x", - "read": { "fn": "none" } + "read": { + "fn": "none" + } }, { "name": "state/y", - "read": { "fn": "none" } + "read": { + "fn": "none" + } }, { "name": "state/ct", - "read": { "fn": "none" } + "read": { + "fn": "none" + } }, { "name": "state/reachable" From dc8533794dde101b496f793c15369bc577c00430 Mon Sep 17 00:00:00 2001 From: ebaauw Date: Mon, 11 Sep 2023 20:36:28 +0200 Subject: [PATCH 10/12] Update lumi_light_acn132.json --- devices/xiaomi/lumi_light_acn132.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/devices/xiaomi/lumi_light_acn132.json b/devices/xiaomi/lumi_light_acn132.json index d0af0dbb36..c4066264c6 100644 --- a/devices/xiaomi/lumi_light_acn132.json +++ b/devices/xiaomi/lumi_light_acn132.json @@ -281,11 +281,11 @@ }, { "name": "state/on", - "refresh.interval": 365 + "refresh.interval": 360 }, { "name": "state/bri", - "refresh.interval": 365 + "refresh.interval": 360 }, { "name": "state/colormode", @@ -307,7 +307,7 @@ "0x0007" ] }, - "refresh.interval": 365 + "refresh.interval": 360 }, { "name": "state/music_sync", From 2988bd228216386624cf1af248e0d77abc3ffb38 Mon Sep 17 00:00:00 2001 From: ebaauw Date: Mon, 11 Sep 2023 22:29:27 +0200 Subject: [PATCH 11/12] Update lumi_light_acn132.json --- devices/xiaomi/lumi_light_acn132.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/devices/xiaomi/lumi_light_acn132.json b/devices/xiaomi/lumi_light_acn132.json index c4066264c6..305c6e3cce 100644 --- a/devices/xiaomi/lumi_light_acn132.json +++ b/devices/xiaomi/lumi_light_acn132.json @@ -1,9 +1,11 @@ { "schema": "devcap1.schema.json", "manufacturername": [ - "$MF_AQARA" + "$MF_AQARA", + "$MF_LUMI" ], "modelid": [ + "lumi.light.acn132", "lumi.light.acn132" ], "product": "Aqara LED Strip T1", @@ -244,7 +246,7 @@ "mf": "0x115F", "at": "0x051B", "dt": "0x20", - "eval": "Math.max(5, Math.min(Attr.val, 50))" + "eval": "Math.max(5, Math.min(Item.val, 50))" } }, { From f0d8a87c97be6dc01fde8a55486b6e212343b999 Mon Sep 17 00:00:00 2001 From: ebaauw Date: Tue, 12 Sep 2023 21:20:02 +0200 Subject: [PATCH 12/12] Update light_node.cpp Dirty hack to prevent `state/effect` on `lumi.light.acn132`, but `setHaEndpoint()` is invoked before Device is available or _Manufacturer Code_, _Manufacturer Name_, and _Model Identifier_ have been read. --- light_node.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/light_node.cpp b/light_node.cpp index 5469f1540b..9ce84c3fa1 100644 --- a/light_node.cpp +++ b/light_node.cpp @@ -424,6 +424,11 @@ void LightNode::setHaEndpoint(const deCONZ::SimpleDescriptor &endpoint) { removeItem(RCapColorCapabilities); } + // else if (modelId() == QLatin1String("lumi.light.acn132")) + else if (deviceId == DEV_ID_HA_COLOR_DIMMABLE_LIGHT && manufacturerCode() == 0 && + manufacturer().isEmpty() && modelId().isEmpty()) + { + } else { addItem(DataTypeString, RStateEffect)->setValue(RStateEffectValues[R_EFFECT_NONE]);