From 2503cb9d0374f2594a0f331b47313773b792431c Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Thu, 18 Feb 2021 20:04:41 +0100 Subject: [PATCH] Zigbee fix cc2652 init and permitjoin --- tasmota/xdrv_23_zigbee_0_constants.ino | 3 +- tasmota/xdrv_23_zigbee_1_headers.ino | 10 ++- tasmota/xdrv_23_zigbee_7_0_statemachine.ino | 68 ++++++++++++++--- tasmota/xdrv_23_zigbee_8_parsers.ino | 29 ++++---- tasmota/xdrv_23_zigbee_A_impl.ino | 82 +++++++++++---------- 5 files changed, 128 insertions(+), 64 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_0_constants.ino b/tasmota/xdrv_23_zigbee_0_constants.ino index f29c787c6..d7a5a7aad 100644 --- a/tasmota/xdrv_23_zigbee_0_constants.ino +++ b/tasmota/xdrv_23_zigbee_0_constants.ino @@ -901,7 +901,8 @@ enum Z_configuration { CONF_NWKMGR_ADDR = 0x89, CONF_ZDO_DIRECT_CB = 0x8F, CONF_TCLK_TABLE_START = 0x0101, - ZNP_HAS_CONFIGURED = 0xF00 + ZNP_HAS_CONFIGURED = 0xF00, + ZNP_HAS_CONFIGURED3 = 0x60, // different attribute address for ZStack 3 }; // diff --git a/tasmota/xdrv_23_zigbee_1_headers.ino b/tasmota/xdrv_23_zigbee_1_headers.ino index 0ec1a7af3..ba01ded30 100644 --- a/tasmota/xdrv_23_zigbee_1_headers.ino +++ b/tasmota/xdrv_23_zigbee_1_headers.ino @@ -79,6 +79,7 @@ const uint8_t ZIGBEE_LABEL_START_ROUTER = 13; // Start ZNP as router const uint8_t ZIGBEE_LABEL_INIT_DEVICE = 14; // Init ZNP as end-device const uint8_t ZIGBEE_LABEL_START_DEVICE = 15; // Start ZNP as end-device const uint8_t ZIGBEE_LABEL_START_ROUTER_DEVICE = 16; // Start common to router and device +const uint8_t ZIGBEE_LABEL_ZB3_INIT = 17; // check parameters for ZB3 const uint8_t ZIGBEE_LABEL_FACT_RESET_ROUTER_DEVICE_POST = 19; // common post configuration for router and device const uint8_t ZIGBEE_LABEL_READY = 20; // goto label 20 for main loop const uint8_t ZIGBEE_LABEL_MAIN_LOOP = 21; // main loop @@ -113,6 +114,11 @@ public: bool recv_until = false; // ignore all messages until the received frame fully matches bool eeprom_present = false; // is the ZBBridge EEPROM present? bool eeprom_ready = false; // is the ZBBridge EEPROM formatted and ready? +#ifdef USE_ZIGBEE_ZNP + bool zb3 = false; // true if ZStack 3.x, false if ZStack 1.2 +#else + bool zb3 = true; // always ZB3 with EZSP +#endif // USE_ZIGBEE_ZNP // Zigbee mapping bool mapping_in_progress = false; // is there a mapping in progress bool mapping_ready = false; // do we have mapping information ready @@ -131,11 +137,9 @@ public: // Energy scan int8_t energy[USE_ZIGBEE_CHANNEL_COUNT]; + uint32_t permit_end_time = 0; // timestamp when permit join ends, with ZNP 1.2, it takes only 0 (off) and -1 (on) #ifdef USE_ZIGBEE_EZSP - uint32_t permit_end_time = 0; // timestamp when permit join ends uint16_t ezsp_version = 0; -#elif defined(USE_ZIGBEE_ZNP) - bool permit_end_time = false; // in ZNP mode it's only a boolean #endif #ifdef USE_ZIGBEE_EZSP diff --git a/tasmota/xdrv_23_zigbee_7_0_statemachine.ino b/tasmota/xdrv_23_zigbee_7_0_statemachine.ino index b413e1092..bb50d300c 100644 --- a/tasmota/xdrv_23_zigbee_7_0_statemachine.ino +++ b/tasmota/xdrv_23_zigbee_7_0_statemachine.ino @@ -94,6 +94,7 @@ enum Zigbee_StateMachine_Instruction_Set { #define ZI_STOP(x) { .i = { ZGB_INSTR_STOP, (x), 0x0000} }, #define ZI_CALL(f, x) { .i = { ZGB_INSTR_CALL, (x), 0x0000} }, { .p = (const void*)(f) }, +// #define ZI_CALL2(f, x, y) { .i = { ZGB_INSTR_CALL, (x), (y)} }, { .p = (const void*)(f) }, #define ZI_LOG(x, m) { .i = { ZGB_INSTR_LOG, (x), 0x0000 } }, { .p = ((const void*)(m)) }, #define ZI_MQTT_STATE(x, m) { .i = { ZGB_INSTR_MQTT_STATE, (x), 0x0000 } }, { .p = ((const void*)(m)) }, #define ZI_ON_RECV_UNEXPECTED(f) { .i = { ZGB_ON_RECV_UNEXPECTED, 0x00, 0x0000} }, { .p = (const void*)(f) }, @@ -149,7 +150,7 @@ ZBM(ZBS_VERSION, Z_SREQ | Z_SYS, SYS_VERSION ) // 2102 Z_SYS:versio ZBM(ZBR_VERSION, Z_SRSP | Z_SYS, SYS_VERSION ) // 6102 Z_SYS:version // Check if ZNP_HAS_CONFIGURED is set -ZBM(ZBS_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_READ, ZNP_HAS_CONFIGURED & 0xFF, ZNP_HAS_CONFIGURED >> 8, 0x00 /* offset */ ) // 2108000F00 - 6108000155 +ZBR(ZBS_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_READ, ZNP_HAS_CONFIGURED & 0xFF, ZNP_HAS_CONFIGURED >> 8, 0x00 /* offset */ ) // 2108000F00 - 6108000155 ZBM(ZBR_ZNPHC, Z_SRSP | Z_SYS, SYS_OSAL_NV_READ, Z_SUCCESS, 0x01 /* len */, 0x55) // 6108000155 // If not set, the response is 61-08-02-00 = Z_SRSP | Z_SYS, SYS_OSAL_NV_READ, Z_INVALIDPARAMETER, 0x00 /* len */ @@ -169,8 +170,16 @@ ZBR(ZBR_CHANN, Z_SRSP | Z_SYS, SYS_OSAL_NV_READ, Z_SUCCESS, Z_B0(USE_ZIGBEE_CHANNEL_MASK), Z_B1(USE_ZIGBEE_CHANNEL_MASK), Z_B2(USE_ZIGBEE_CHANNEL_MASK), Z_B3(USE_ZIGBEE_CHANNEL_MASK), ) // 61080004xxxxxxxx -ZBM(ZBS_PFGK, Z_SREQ | Z_SYS, SYS_OSAL_NV_READ, CONF_PRECFGKEY,0x00, 0x00 ) // 2108620000 -ZBR(ZBR_PFGK, Z_SRSP | Z_SYS, SYS_OSAL_NV_READ, Z_SUCCESS, +ZBM(ZBS_PFGK, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PRECFGKEY ) // 260462 +ZBR(ZBR_PFGK, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_PRECFGKEY, + 0x10 /* len */, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* key_l */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* key_h */ + /*0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, + 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0D*/ ) // 660400621001030507090B0D0F00020406080A0C0D + +ZBM(ZBS_PFGK3, Z_SREQ | Z_SYS, SYS_OSAL_NV_READ, CONF_PRECFGKEY,0x00, 0x00 ) // 2108620000 +ZBR(ZBR_PFGK3, Z_SRSP | Z_SYS, SYS_OSAL_NV_READ, Z_SUCCESS, 0x10 /* len */, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* key_l */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* key_h */ @@ -238,14 +247,14 @@ ZBM(ZBS_WNV_SECMODE, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, Z_B0(CONF_TCLK_TABLE_STA // Write Z_ZDO Direct CB ZBM(ZBS_W_ZDODCB, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, CONF_ZDO_DIRECT_CB,0x00, 0x00, 0x01 /* len */, 0x01 ) // 21098F00000101 // NV Init ZNP Has Configured -ZBM(ZBS_WNV_INITZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_ITEM_INIT, ZNP_HAS_CONFIGURED & 0xFF, ZNP_HAS_CONFIGURED >> 8, +ZBR(ZBS_WNV_INITZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_ITEM_INIT, ZNP_HAS_CONFIGURED & 0xFF, ZNP_HAS_CONFIGURED >> 8, 0x01, 0x00 /* InitLen 16 bits */, 0x01 /* len */, 0x00 ) // 2107000F01000100 - 610709 // Init succeeded //ZBM(ZBR_WNV_INIT_OK, Z_SRSP | Z_SYS, SYS_OSAL_NV_ITEM_INIT, Z_CREATED ) // 610709 - NV Write ZBM(ZBR_WNV_INIT_OK, Z_SRSP | Z_SYS, SYS_OSAL_NV_ITEM_INIT ) // 6107xx, Success if 610700 or 610709 - NV Write // Write ZNP Has Configured -ZBM(ZBS_WNV_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, Z_B0(ZNP_HAS_CONFIGURED), Z_B1(ZNP_HAS_CONFIGURED), +ZBR(ZBS_WNV_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, Z_B0(ZNP_HAS_CONFIGURED), Z_B1(ZNP_HAS_CONFIGURED), 0x00 /* offset */, 0x01 /* len */, 0x55 ) // 2109000F000155 - 610900 // Z_ZDO:startupFromApp ZBM(ZBS_STARTUPFROMAPP, Z_SREQ | Z_ZDO, ZDO_STARTUP_FROM_APP, 100, 0 /* delay */) // 25406400 @@ -333,8 +342,17 @@ void ZNP_UpdateConfig(uint8_t zb_channel, uint16_t zb_pan_id, uint64_t zb_ext_pa 0x04 /* len */, Z_B0(zb_channel_mask), Z_B1(zb_channel_mask), Z_B2(zb_channel_mask), Z_B3(zb_channel_mask), ) // 61080004xxxxxxxx - - ZBW(ZBR_PFGK, Z_SRSP | Z_SYS, SYS_OSAL_NV_READ, Z_SUCCESS, + // Zstack 1.2 + ZBW(ZBR_PFGK, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_PRECFGKEY, + 0x10 /* len */, + Z_B0(zb_precfgkey_l), Z_B1(zb_precfgkey_l), Z_B2(zb_precfgkey_l), Z_B3(zb_precfgkey_l), + Z_B4(zb_precfgkey_l), Z_B5(zb_precfgkey_l), Z_B6(zb_precfgkey_l), Z_B7(zb_precfgkey_l), + Z_B0(zb_precfgkey_h), Z_B1(zb_precfgkey_h), Z_B2(zb_precfgkey_h), Z_B3(zb_precfgkey_h), + Z_B4(zb_precfgkey_h), Z_B5(zb_precfgkey_h), Z_B6(zb_precfgkey_h), Z_B7(zb_precfgkey_h), + /*0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, + 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0D*/ ) // 660400621001030507090B0D0F00020406080A0C0D + // ZStack 3 + ZBW(ZBR_PFGK3, Z_SRSP | Z_SYS, SYS_OSAL_NV_READ, Z_SUCCESS, 0x10 /* len */, Z_B0(zb_precfgkey_l), Z_B1(zb_precfgkey_l), Z_B2(zb_precfgkey_l), Z_B3(zb_precfgkey_l), Z_B4(zb_precfgkey_l), Z_B5(zb_precfgkey_l), Z_B6(zb_precfgkey_l), Z_B7(zb_precfgkey_l), @@ -363,6 +381,17 @@ void ZNP_UpdateConfig(uint8_t zb_channel, uint16_t zb_pan_id, uint64_t zb_ext_pa ) // 21096200001001030507090B0D0F00020406080A0C0D } +// Update configuration for ZStack 3 +void ZNP_UpdateZStack3(void) { + ZBW(ZBS_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_READ, ZNP_HAS_CONFIGURED3 & 0xFF, ZNP_HAS_CONFIGURED3 >> 8, 0x00 /* offset */ ) // 2108000F00 - 6108000155 + + ZBW(ZBS_WNV_INITZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_ITEM_INIT, ZNP_HAS_CONFIGURED3 & 0xFF, ZNP_HAS_CONFIGURED3 >> 8, + 0x01, 0x00 /* InitLen 16 bits */, 0x01 /* len */, 0x00 ) // 2107000F01000100 - 610709 + + ZBW(ZBS_WNV_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, Z_B0(ZNP_HAS_CONFIGURED3), Z_B1(ZNP_HAS_CONFIGURED3), + 0x00 /* offset */, 0x01 /* len */, 0x55 ) // 2109000F000155 - 610900 +} + static const Zigbee_Instruction zb_prog[] PROGMEM = { ZI_LABEL(0) ZI_NOOP() @@ -402,10 +431,17 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = { ZI_WAIT_RECV(1000, ZBR_EXTPAN) ZI_SEND(ZBS_CHANN) // check CHANNEL ZI_WAIT_RECV(1000, ZBR_CHANN) - ZI_SEND(ZBS_PFGK) // check PFGK - ZI_WAIT_RECV(1000, ZBR_PFGK) ZI_SEND(ZBS_PFGKEN) // check PFGKEN ZI_WAIT_RECV(1000, ZBR_PFGKEN) + + ZI_CALL(&Z_GotoZB3, ZIGBEE_LABEL_ZB3_INIT) + ZI_SEND(ZBS_PFGK) // check PFGK on ZB1.2 + ZI_WAIT_RECV(1000, ZBR_PFGK) + ZI_GOTO(ZIGBEE_LABEL_START_COORD) + + ZI_LABEL(ZIGBEE_LABEL_ZB3_INIT) + ZI_SEND(ZBS_PFGK3) // check PFGK on ZB3 + ZI_WAIT_RECV(1000, ZBR_PFGK3) //ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "zigbee configuration ok") // all is good, we can start @@ -416,7 +452,7 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = { //ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "starting zigbee coordinator") ZI_SEND(ZBS_STARTUPFROMAPP) // start coordinator ZI_WAIT_RECV(5000, ZBR_STARTUPFROMAPP) // wait for sync ack of command - ZI_WAIT_UNTIL_FUNC(10000, AREQ_STARTUPFROMAPP, &ZNP_ReceiveStateChange) // wait for async message that coordinator started + ZI_WAIT_UNTIL_FUNC(20000, AREQ_STARTUPFROMAPP, &ZNP_ReceiveStateChange) // wait for async message that coordinator started, max 20s ZI_SEND(ZBS_GETDEVICEINFO) // GetDeviceInfo ZI_WAIT_RECV_FUNC(2000, ZBR_GETDEVICEINFO, &ZNP_ReceiveDeviceInfo) //ZI_WAIT_RECV(2000, ZBR_GETDEVICEINFO) // memorize info @@ -1027,6 +1063,7 @@ void ZigbeeStateMachine_Run(void) { if (cur_ptr1) { uint32_t res; res = (*((ZB_Func)cur_ptr1))(cur_d8); + // res = (*((ZB_Func)cur_ptr1))(cur_d8, cur_d16); if (res > 0) { ZigbeeGotoLabel(res); continue; // avoid incrementing PC after goto @@ -1170,4 +1207,15 @@ int32_t ZigbeeProcessInput(SBuffer &buf) { return 0; // Fix GCC 10.1 warning } +// +// Condiditional GOTO depending on ZB3 or not +// Take the branch if ZB3 +int32_t Z_GotoZB3(uint8_t value) { + if (zigbee.zb3) { + return value; // take the branch + } else { + return 0; // continue + } +} + #endif // USE_ZIGBEE diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 2183357a1..04fed0f57 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -227,15 +227,6 @@ int32_t EZ_PermitJoinRsp(int32_t res, const SBuffer &buf) { return -1; } -// -// Special case: EZSP does not send an event for PermitJoin end, so we generate a synthetic one -// -void Z_PermitJoinDisable(void) { - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{\"Status\":20,\"Message\":\"Pairing mode disabled\"}}")); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); -} - - // // Received MessageSentHandler // @@ -254,6 +245,14 @@ int32_t EZ_MessageSent(int32_t res, const SBuffer &buf) { #endif // USE_ZIGBEE_EZSP +// +// Special case: EZSP does not send an event for PermitJoin end, so we generate a synthetic one +// +void Z_PermitJoinDisable(void) { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{\"Status\":20,\"Message\":\"Pairing mode disabled\"}}")); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); +} + /*********************************************************************************************\ * Handle auto-mapping \*********************************************************************************************/ @@ -427,6 +426,10 @@ int32_t ZNP_Reboot(int32_t res, SBuffer &buf) { MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); if ((0x02 == major_rel) && ((0x06 == minor_rel) || (0x07 == minor_rel))) { + if (0x07 == minor_rel) { + zigbee.zb3 = true; // we run Zigbee 3 + ZNP_UpdateZStack3(); // update configuration for ZStack 3 + } return 0; // version 2.6.x and 2.7.x are ok } else { return ZIGBEE_LABEL_UNSUPPORTED_VERSION; // abort @@ -546,18 +549,18 @@ int32_t ZNP_ReceivePermitJoinStatus(int32_t res, const SBuffer &buf) { uint8_t status_code; const char* message; - if (0xFF == duration) { + if (!zigbee.zb3 && (0xFF == duration)) { status_code = ZIGBEE_STATUS_PERMITJOIN_OPEN_XX; message = PSTR("Enable Pairing mode until next boot"); - zigbee.permit_end_time = true; // In ZNP mode, declare permitjoin open + zigbee.permit_end_time = -1; // In ZNP mode, declare permitjoin open } else if (duration > 0) { status_code = ZIGBEE_STATUS_PERMITJOIN_OPEN_60; message = PSTR("Enable Pairing mode for %d seconds"); - zigbee.permit_end_time = true; // In ZNP mode, declare permitjoin open + zigbee.permit_end_time = -1; // In ZNP mode, declare permitjoin open } else { status_code = ZIGBEE_STATUS_PERMITJOIN_CLOSE; message = PSTR("Disable Pairing mode"); - zigbee.permit_end_time = false; // In ZNP mode, declare permitjoin closed + zigbee.permit_end_time = 0; // In ZNP mode, declare permitjoin closed } Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" "\"Status\":%d,\"Message\":\""), diff --git a/tasmota/xdrv_23_zigbee_A_impl.ino b/tasmota/xdrv_23_zigbee_A_impl.ino index 2fdc89846..870315055 100644 --- a/tasmota/xdrv_23_zigbee_A_impl.ino +++ b/tasmota/xdrv_23_zigbee_A_impl.ino @@ -1416,13 +1416,15 @@ void CmndZbPermitJoin(void) { if (payload <= 0) { duration = 0; } - -// ZNP Version -#ifdef USE_ZIGBEE_ZNP if (99 == payload) { + if (zigbee.zb3) { + ResponseCmndChar_P(PSTR("Unlimited time not supported")); return; + } duration = 0xFF; // unlimited time } +// ZNP Version +#ifdef USE_ZIGBEE_ZNP SBuffer buf(34); buf.add8(Z_SREQ | Z_ZDO); // 25 buf.add8(ZDO_MGMT_PERMIT_JOIN_REQ); // 36 @@ -1437,10 +1439,6 @@ void CmndZbPermitJoin(void) { // EZSP VERSION #ifdef USE_ZIGBEE_EZSP - if (99 == payload) { - ResponseCmndChar_P(PSTR("Unlimited time not supported")); return; - } - SBuffer buf(3); buf.add16(EZSP_permitJoining); buf.add8(duration); @@ -1451,18 +1449,21 @@ void CmndZbPermitJoin(void) { buf.add8(duration); buf.add8(0x01); // TC_Significance - This field shall always have a value of 1, indicating a request to change the Trust Center policy. If a frame is received with a value of 0, it shall be treated as having a value of 1. EZ_SendZDO(0xFFFC, ZDO_Mgmt_Permit_Joining_req, buf.buf(), buf.len()); - - // Set Timer after the end of the period, and reset a non-expired previous timer - if (duration > 0) { - // Log pairing mode enabled - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{\"Status\":21,\"Message\":\"Pairing mode enabled\"}}")); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - zigbee.permit_end_time = millis() + duration * 1000; - } else { - zigbee.permit_end_time = millis(); - } #endif // USE_ZIGBEE_EZSP + // Set Timer after the end of the period, and reset a non-expired previous timer + if (zigbee.zb3) { + if (duration > 0) { + // Log pairing mode enabled + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{\"Status\":21,\"Message\":\"Pairing mode enabled\"}}")); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + zigbee.permit_end_time = millis() + duration * 1000; + } else { + zigbee.permit_end_time = millis(); + } + if (0 == zigbee.permit_end_time) { zigbee.permit_end_time = 1; } // avoid very rare case where timer collides with timestamp equals to zero + } + ResponseCmndDone(); } @@ -1498,31 +1499,40 @@ void CmndZbEZSPListen(void) { void ZigbeeGlowPermitJoinLight(void) { static const uint16_t cycle_time = 1000; // cycle up and down in 1000 ms static const uint16_t half_cycle_time = cycle_time / 2; // cycle up and down in 1000 ms + + uint16_t led_power = 0; // turn led off if (zigbee.permit_end_time) { - uint16_t led_power = 0; // turn led off + uint32_t millis_to_go = millis() - zigbee.permit_end_time; + uint32_t sub_second = millis_to_go % cycle_time; + if (sub_second <= half_cycle_time) { + led_power = changeUIntScale(sub_second, 0, half_cycle_time, 0, 1023); + } else { + led_power = changeUIntScale(sub_second, half_cycle_time, cycle_time, 1023, 0); + } + led_power = ledGamma10_10(led_power); + } + + // change the led state + int led_pin = Pin(GPIO_LEDLNK); + if (led_pin >= 0) { + analogWrite(led_pin, TasmotaGlobal.ledlnk_inverted ? 1023 - led_power : led_power); + } +} +#endif // USE_ZIGBEE_EZSP + +// check if the permitjoin timer has expired +void ZigbeePermitJoinUpdate(void) { + if (zigbee.zb3 && zigbee.permit_end_time) { // permit join is ongoing if (TimeReached(zigbee.permit_end_time)) { zigbee.permit_end_time = 0; // disable timer Z_PermitJoinDisable(); - } else { - uint32_t millis_to_go = millis() - zigbee.permit_end_time; - uint32_t sub_second = millis_to_go % cycle_time; - if (sub_second <= half_cycle_time) { - led_power = changeUIntScale(sub_second, 0, half_cycle_time, 0, 1023); - } else { - led_power = changeUIntScale(sub_second, half_cycle_time, cycle_time, 1023, 0); - } - led_power = ledGamma10_10(led_power); - } - - // change the led state - int led_pin = Pin(GPIO_LEDLNK); - if (led_pin >= 0) { - analogWrite(led_pin, TasmotaGlobal.ledlnk_inverted ? 1023 - led_power : led_power); } +#ifdef USE_ZIGBEE_EZSP + ZigbeeGlowPermitJoinLight(); // update glowing light accordingly +#endif // USE_ZIGBEE_EZSP } } -#endif // USE_ZIGBEE_EZSP // // Command `ZbStatus` @@ -2144,9 +2154,7 @@ bool Xdrv23(uint8_t function) if (ZigbeeSerial) { ZigbeeInputLoop(); ZigbeeOutputLoop(); // send any outstanding data -#ifdef USE_ZIGBEE_EZSP - ZigbeeGlowPermitJoinLight(); -#endif // USE_ZIGBEE_EZSP + ZigbeePermitJoinUpdate(); // timer for permit join } if (zigbee.state_machine) { ZigbeeStateMachine_Run();