diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index f42ee4ca1..237d131b3 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -2,6 +2,8 @@ ### 8.4.0.1 20200730 +- Add Zigbee better support for IKEA Motion Sensor + ### 8.4.0 20200730 - Release George diff --git a/tasmota/xdrv_23_zigbee_0_constants.ino b/tasmota/xdrv_23_zigbee_0_constants.ino index 62b3652af..5ebd66087 100644 --- a/tasmota/xdrv_23_zigbee_0_constants.ino +++ b/tasmota/xdrv_23_zigbee_0_constants.ino @@ -26,6 +26,8 @@ #error "You must select one of: #define USE_ZIGBEE_ZNP or #define USE_ZIGBEE_EZSP" #endif +// #define USE_ZIGBEE_NO_READ_ATTRIBUTES // disable automatic READ ATTRIBUTES generated by Z2T - for debugging only + #define OCCUPANCY "Occupancy" // global define for Aqara #define ZIGBEE_EZSP_RESET_LED 4 // Led number to drive the EZSP Reset pin diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index 454e9b5cf..aa9d7513f 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -1158,7 +1158,9 @@ void ZCLFrame::parseResponse(void) { // Parse non-normalized attributes void ZCLFrame::parseClusterSpecificCommand(JsonObject& json, uint8_t offset) { convertClusterSpecific(json, _cluster_id, _cmd_id, _frame_control.b.direction, _srcaddr, _srcendpoint, _payload); +#ifndef USE_ZIGBEE_NO_READ_ATTRIBUTES // read attributes unless disabled sendHueUpdate(_srcaddr, _groupaddr, _cluster_id, _cmd_id, _frame_control.b.direction); +#endif } // ====================================================================== diff --git a/tasmota/xdrv_23_zigbee_6_commands.ino b/tasmota/xdrv_23_zigbee_6_commands.ino index c2ea81765..39da3049b 100644 --- a/tasmota/xdrv_23_zigbee_6_commands.ino +++ b/tasmota/xdrv_23_zigbee_6_commands.ino @@ -56,8 +56,8 @@ ZF(ColorTempStep) ZF(ColorTempStepUp) ZF(ColorTempStepDown) ZF(ArrowClick) ZF(ArrowHold) ZF(ArrowRelease) ZF(ZoneStatusChange) ZF(xxxx00) ZF(xxxx) ZF(01xxxx) ZF(03xxxx) ZF(00) ZF(01) ZF() ZF(xxxxyy) ZF(00190200) ZF(01190200) ZF(xxyyyy) ZF(xx) -ZF(xx000A00) ZF(xx0A00) ZF(xxyy0A00) ZF(xxxxyyyy0A00) ZF(xxxx0A00) ZF(xx0A) -ZF(xx190A00) ZF(xx19) ZF(xx190A) ZF(xxxxyyyy) ZF(xxxxyyzz) ZF(xxyyzzzz) ZF(xxyyyyzz) +ZF(xx000A00) ZF(xx0A00) ZF(xxyy0A00) ZF(xxxxyyyy0A00) ZF(xxxx0A00) ZF(xx0A) ZF(xxyy) +ZF(xx190A00) ZF(xx19) ZF(xx190A) ZF(xxxxyyyy) ZF(xxxxyyzz) ZF(xxyyzzzz) ZF(xxyyyyzz) ZF(xxyyyyzzzz) ZF(01xxxx000000000000) ZF(03xxxx000000000000) ZF(00xxxx000000000000) ZF(xxyyyy000000000000) ZF(00xx0A00) ZF(01xx0A00) ZF(03xx0A00) ZF(01xxxx0A0000000000) ZF(03xxxx0A0000000000) ZF(xxyyyy0A0000000000) @@ -84,6 +84,9 @@ const Z_CommandConverter Z_Commands[] PROGMEM = { { Z(RecallScene), 0x0005, 0x05, 0x01, Z(xxxxyy) }, { Z(GetSceneMembership),0x0005, 0x06, 0x01, Z(xxxx) }, // Light & Shutter commands + { Z(Power), 0x0006, 0x40, 0x81, Z(xxyy) }, // Power Off With Effect + { Z(Power), 0x0006, 0x41, 0x81, Z() }, // Power On With Recall Global Scene + { Z(Power), 0x0006, 0x42, 0x81, Z(xxyyyyzzzz) }, // Power On with Timed Off { Z(Power), 0x0006, 0xFF, 0x01, Z() }, // 0=Off, 1=On, 2=Toggle { Z(Dimmer), 0x0008, 0x04, 0x01, Z(xx0A00) }, // Move to Level with On/Off, xx=0..254 (255 is invalid) { Z(DimmerUp), 0x0008, 0x06, 0x01, Z(00190200) }, // Step up by 10%, 0.2 secs @@ -464,6 +467,21 @@ void convertClusterSpecific(JsonObject& json, uint16_t cluster, uint8_t cmd, boo json[F("GroupId")] = xyz.z; String scene_payload = json[attrid_str]; json[F("ScenePayload")] = scene_payload.substring(8); // remove first 8 characters + } else if ((cluster == 0x0006) && (cmd == 0x40)) { + // Power Off With Effect + json[command_name] = 0; // always "Power":0 + json[command_name2 + F("Effect")] = xyz.x; + json[command_name2 + F("EffectVariant")] = xyz.y; + } else if ((cluster == 0x0006) && (cmd == 0x41)) { + // Power On With Recall Global Scene + json[command_name] = 1; // always "Power":1 + json[command_name2 + F("RecallGlobalScene")] = true; + } else if ((cluster == 0x0006) && (cmd == 0x42)) { + // Power On With Timed Off Command + json[command_name] = 1; // always "Power":1 + json[command_name2 + F("OnlyWhenOn")] = xyz.x; + json[command_name2 + F("OnTime")] = xyz.y / 10.0f; + json[command_name2 + F("OffWait")] = xyz.z / 10.0f; } } else { // general case bool extended_command = false; // do we send command with endpoint suffix diff --git a/tasmota/xdrv_23_zigbee_7_statemachine.ino b/tasmota/xdrv_23_zigbee_7_statemachine.ino index 784a5ebf3..ce741c027 100644 --- a/tasmota/xdrv_23_zigbee_7_statemachine.ino +++ b/tasmota/xdrv_23_zigbee_7_statemachine.ino @@ -904,7 +904,9 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = { ZI_LOG(LOG_LEVEL_INFO, kZigbeeStarted) ZI_CALL(&Z_State_Ready, 1) // Now accept incoming messages ZI_CALL(&Z_Load_Devices, 0) +#ifndef USE_ZIGBEE_NO_READ_ATTRIBUTES ZI_CALL(&Z_Query_Bulbs, 0) +#endif ZI_LABEL(ZIGBEE_LABEL_MAIN_LOOP) ZI_WAIT_FOREVER() diff --git a/tasmota/xdrv_23_zigbee_A_impl.ino b/tasmota/xdrv_23_zigbee_A_impl.ino index 076ed7d4a..13b7bb749 100644 --- a/tasmota/xdrv_23_zigbee_A_impl.ino +++ b/tasmota/xdrv_23_zigbee_A_impl.ino @@ -179,7 +179,9 @@ void zigbeeZCLSendStr(uint16_t shortaddr, uint16_t groupaddr, uint8_t endpoint, ZigbeeZCLSend_Raw(shortaddr, groupaddr, cluster, endpoint, cmd, clusterSpecific, manuf, buf.getBuffer(), buf.len(), true, zigbee_devices.getNextSeqNumber(shortaddr)); // now set the timer, if any, to read back the state later if (clusterSpecific) { +#ifndef USE_ZIGBEE_NO_READ_ATTRIBUTES // read back attribute value unless it is disabled zigbeeSetCommandTimer(shortaddr, groupaddr, cluster, endpoint); +#endif } }