Merge pull request #9038 from s-hadinger/zigbee_ezsp_ikea

Zigbee EZSP fixes
This commit is contained in:
Theo Arends 2020-08-06 09:20:46 +02:00 committed by GitHub
commit 3f8398ce79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 70 additions and 22 deletions

View File

@ -434,6 +434,23 @@ enum EZSP_EmberOutgoingMessageType {
EMBER_OUTGOING_BROADCAST = 0x06
};
enum EZSP_EmberKeyStructBitmask {
EMBER_KEY_HAS_SEQUENCE_NUMBER = 0x0001,
EMBER_KEY_HAS_OUTGOING_FRAME_COUNTER = 0x0002,
EMBER_KEY_HAS_INCOMING_FRAME_COUNTER = 0x0004,
EMBER_KEY_HAS_PARTNER_EUI64 = 0x0008,
EMBER_KEY_IS_AUTHORIZED = 0x0010,
EMBER_KEY_PARTNER_IS_SLEEPY = 0x0020,
EMBER_UNCONFIRMED_TRANSIENT_KEY = 0x0040
};
enum EZSP_EmberKeyType {
EMBER_TRUST_CENTER_LINK_KEY = 1,
EMBER_CURRENT_NETWORK_KEY = 3,
EMBER_NEXT_NETWORK_KEY = 4,
EMBER_APPLICATION_LINK_KEY = 5
};
// inspired from https://github.com/zigpy/zigpy/blob/dev/zigpy/zdo/types.py
enum EZSP_ZDO {
ZDO_NWK_addr_req = 0x0000,

View File

@ -84,6 +84,7 @@ 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, 0xFF, 0x01, Z() }, // 0=Off, 1=On, 2=Toggle
{ 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

View File

@ -186,6 +186,7 @@ const char kZNP12[] PROGMEM = "Only ZNP 1.2 is currently supported";
const char kEZ8[] PROGMEM = "Only EZSP protocol v8 is currently supported";
const char kAbort[] PROGMEM = "Abort";
const char kZigbeeAbort[] PROGMEM = D_LOG_ZIGBEE "Abort";
const char kZigbeeGroup0[] PROGMEM = D_LOG_ZIGBEE "Subscribe to group 0 'ZbListen0 0'";
#ifdef USE_ZIGBEE_ZNP
@ -746,23 +747,30 @@ ZBM(ZBR_GET_EUI64, EZSP_getEui64, 0x00 /*high*/) // 2600
ZBM(ZBS_GET_NODEID, EZSP_getNodeId, 0x00 /*high*/) // 2700
ZBM(ZBR_GET_NODEID, EZSP_getNodeId, 0x00 /*high*/) // 2700
// auto subscribe to group 0 in slot 0
ZBM(ZBS_SET_MCAST_ENTRY, EZSP_setMulticastTableEntry, 0x00 /*high*/,
0x00 /* slot */, 0x00,0x00 /* group */, 0x01 /* endpoint */, 0x00 /* network */) // 64000000000100
ZBM(ZBR_SET_MCAST_ENTRY, EZSP_setMulticastTableEntry, 0x00 /*high*/, 0x00 /* status */)
// check the network key
// getCurrentSecurityState
// TODO double check the security bitmask
ZBM(ZBS_GET_CURR_SEC, EZSP_getCurrentSecurityState, 0x00 /*high*/) // 6900
ZBR(ZBR_GET_CURR_SEC, EZSP_getCurrentSecurityState, 0x00 /*high*/,
0x00 /*status*/,
0x7C, 0x00 /*Current Security Bitmask*/,
) // 6900...
ZBM(ZBS_GET_KEY_NWK, EZSP_getKey, 0x00 /*high*/, EMBER_CURRENT_NETWORK_KEY) // 6A0003
ZBM(ZBR_GET_KEY_NWK, EZSP_getKey, 0x00 /*high*/, 0x00 /*status*/) // 6A0000...
/*********************************************************************************************\
* Update the relevant commands with Settings
\*********************************************************************************************/
//
uint64_t ezsp_key_low, ezsp_key_high;
void EZ_UpdateConfig(uint8_t zb_channel, uint16_t zb_pan_id, uint64_t zb_ext_panid, uint64_t zb_precfgkey_l, uint64_t zb_precfgkey_h, uint8_t zb_txradio_dbm) {
uint8_t txradio = zb_txradio_dbm;
// restrict txradio to acceptable range, and use default otherwise
if (txradio == 0) { txradio = USE_ZIGBEE_TXRADIO_DBM; }
if (txradio > 20) { txradio = USE_ZIGBEE_TXRADIO_DBM; }
ezsp_key_low = zb_precfgkey_l;
ezsp_key_high = zb_precfgkey_h;
ZBW(ZBS_SET_SECURITY, EZSP_setInitialSecurityState, 0x00 /*high*/,
Z_B0(EZ_SECURITY_MODE), Z_B1(EZ_SECURITY_MODE),
@ -789,15 +797,15 @@ void EZ_UpdateConfig(uint8_t zb_channel, uint16_t zb_pan_id, uint64_t zb_ext_pan
0x00,0x00,0x00,0x00, /*NWK channel mask, unused*/
) // 1E00...
ZBW(ZBR_CHECK_NETW_PARM, EZSP_getNetworkParameters, 0x00 /*high*/,
0x00 /*status*/,
EMBER_COORDINATOR /*0x01*/,
Z_B0(zb_ext_panid), Z_B1(zb_ext_panid), Z_B2(zb_ext_panid), Z_B3(zb_ext_panid),
Z_B4(zb_ext_panid), Z_B5(zb_ext_panid), Z_B6(zb_ext_panid), Z_B7(zb_ext_panid),
Z_B0(zb_pan_id), Z_B1(zb_pan_id),
txradio /*radioTxPower*/,
zb_channel /*channel*/,
) // 2800...
ZBW(ZBR_CHECK_NETW_PARM, EZSP_getNetworkParameters, 0x00 /*high*/,
0x00 /*status*/,
EMBER_COORDINATOR /*0x01*/,
Z_B0(zb_ext_panid), Z_B1(zb_ext_panid), Z_B2(zb_ext_panid), Z_B3(zb_ext_panid),
Z_B4(zb_ext_panid), Z_B5(zb_ext_panid), Z_B6(zb_ext_panid), Z_B7(zb_ext_panid),
Z_B0(zb_pan_id), Z_B1(zb_pan_id),
txradio /*radioTxPower*/,
zb_channel /*channel*/,
) // 2800...
}
static const Zigbee_Instruction zb_prog[] PROGMEM = {
@ -857,21 +865,18 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
ZI_SEND(ZBS_SET_POLICY_05) ZI_WAIT_RECV(500, ZBR_SET_POLICY_XX)
ZI_SEND(ZBS_SET_POLICY_06) ZI_WAIT_RECV(500, ZBR_SET_POLICY_XX)
// set encryption keys
ZI_SEND(ZBS_SET_SECURITY) ZI_WAIT_RECV(500, ZBR_SET_SECURITY)
// Decide whether we try 'networkInit()' to restore configuration, or create a new network
ZI_CALL(&EZ_GotoIfResetConfig, ZIGBEE_LABEL_CONFIGURE_EZSP) // goto ZIGBEE_LABEL_CONFIGURE_EZSP if reset_config is set
// ZI_GOTO(ZIGBEE_LABEL_CONFIGURE_EZSP)
// // Try networkInit to restore settings, and check if network comes up
// Try networkInit to restore settings, and check if network comes up
ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_BAD_CONFIG) //
ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_BAD_CONFIG)
ZI_SEND(ZBS_NETWORK_INIT) ZI_WAIT_RECV(500, ZBR_NETWORK_INIT)
ZI_WAIT_RECV(1500, ZBR_NETWORK_UP) // wait for network to start
// check if configuration is ok
ZI_SEND(ZBS_GET_CURR_SEC) ZI_WAIT_RECV(500, ZBR_GET_CURR_SEC)
ZI_SEND(ZBS_GET_KEY_NWK) ZI_WAIT_RECV_FUNC(500, ZBR_GET_KEY_NWK, &EZ_CheckKeyNWK)
ZI_SEND(ZBS_GET_EUI64) ZI_WAIT_RECV_FUNC(500, ZBR_GET_EUI64, &EZ_GetEUI64)
ZI_SEND(ZBS_GET_NETW_PARM) ZI_WAIT_RECV_FUNC(500, ZBR_CHECK_NETW_PARM, &EZ_NetworkParameters)
@ -887,6 +892,8 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
// Set back normal error handlers
ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT)
ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT)
// set encryption keys
ZI_SEND(ZBS_SET_SECURITY) ZI_WAIT_RECV(500, ZBR_SET_SECURITY)
// formNetwork
ZI_SEND(ZBS_FORM_NETWORK) ZI_WAIT_RECV(500, ZBR_FORM_NETWORK)
ZI_WAIT_RECV(5000, ZBR_NETWORK_UP) // wait for network to start
@ -898,8 +905,11 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
// Query device information
ZI_SEND(ZBS_GET_EUI64) ZI_WAIT_RECV_FUNC(500, ZBR_GET_EUI64, &EZ_GetEUI64)
ZI_SEND(ZBS_GET_NODEID) ZI_WAIT_RECV_FUNC(500, ZBR_GET_NODEID, &EZ_GetNodeId)
// auto-register multicast group 0x0000
ZI_LOG(LOG_LEVEL_INFO, kZigbeeGroup0)
ZI_SEND(ZBS_SET_MCAST_ENTRY) ZI_WAIT_RECV(500, ZBR_SET_MCAST_ENTRY)
ZI_LABEL(ZIGBEE_LABEL_READY)
// ZI_LABEL(ZIGBEE_LABEL_READY)
ZI_MQTT_STATE(ZIGBEE_STATUS_OK, kStarted)
ZI_LOG(LOG_LEVEL_INFO, kZigbeeStarted)
ZI_CALL(&Z_State_Ready, 1) // Now accept incoming messages

View File

@ -125,6 +125,25 @@ int32_t EZ_NetworkParameters(int32_t res, class SBuffer &buf) {
return res;
}
//
// Analyze response to "getKey" and check NWK key
//
int32_t EZ_CheckKeyNWK(int32_t res, class SBuffer &buf) {
uint8_t status = buf.get8(2);
uint16_t bitmask = buf.get16(3);
uint8_t key_type = buf.get8(5);
uint64_t key_low = buf.get64(6);
uint64_t key_high = buf.get64(14);
if ( (key_type == EMBER_CURRENT_NETWORK_KEY) &&
(key_low == ezsp_key_low) &&
(key_high == ezsp_key_high) ) {
return 0; // proceed to next step
} else {
return -2; // error state
}
}
//
// Handle a "incomingRouteErrorHandler" incoming message
//

View File

@ -594,6 +594,7 @@ int32_t ZigbeeProcessInputEZSP(class SBuffer &buf) {
case EZSP_setMulticastTableEntry: // 6400
case EZSP_setInitialSecurityState: // 6800
case EZSP_getCurrentSecurityState: // 6900
case EZSP_getKey: // 6A00
log_level = LOG_LEVEL_DEBUG;
break;
}

View File

@ -695,7 +695,7 @@ void ZbBindUnbind(bool unbind) { // false = bind, true = unbind
if (0 == dstLongAddr) { ResponseCmndChar_P(PSTR("Unknown dest IEEE address")); return; }
const JsonVariant &val_toendpoint = GetCaseInsensitive(json, PSTR("ToEndpoint"));
if (nullptr != &val_toendpoint) { toendpoint = strToUInt(val_endpoint); } else { toendpoint = endpoint; }
if (nullptr != &val_toendpoint) { toendpoint = strToUInt(val_toendpoint); } else { toendpoint = endpoint; }
}
// Or Group Address - we don't need a dstEndpoint in this case
@ -1063,7 +1063,7 @@ void CmndZbPermitJoin(void) {
void CmndZbEZSPListen(void) {
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
int32_t index = XdrvMailbox.index - 1; // 0 based
int32_t index = XdrvMailbox.index; // 0 is reserved for group 0 (auto-config)
int32_t group = XdrvMailbox.payload;
if (group <= 0) {