mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-25 11:46:31 +00:00
Merge pull request #10024 from s-hadinger/zigbee_zbmap_
Zigbee auto-mapping
This commit is contained in:
commit
de949fe0f1
@ -20,6 +20,8 @@
|
|||||||
#ifdef USE_ZIGBEE
|
#ifdef USE_ZIGBEE
|
||||||
|
|
||||||
#ifdef USE_ZIGBEE_EZSP
|
#ifdef USE_ZIGBEE_EZSP
|
||||||
|
void EZ_SendZDO(uint16_t shortaddr, uint16_t cmd, const unsigned char *payload, size_t payload_len, bool retry = true);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Trying to get a uniform LQI measure, we are aligning with the definition of ZNP
|
// Trying to get a uniform LQI measure, we are aligning with the definition of ZNP
|
||||||
// I.e. a linear projection from -87dBm to +10dB over 0..255
|
// I.e. a linear projection from -87dBm to +10dB over 0..255
|
||||||
@ -200,6 +202,44 @@ int32_t EZ_MessageSent(int32_t res, const class SBuffer &buf) {
|
|||||||
|
|
||||||
#endif // USE_ZIGBEE_EZSP
|
#endif // USE_ZIGBEE_EZSP
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Handle auto-mapping
|
||||||
|
\*********************************************************************************************/
|
||||||
|
// low-level sending of packet
|
||||||
|
void Z_Send_State_or_Map(uint16_t shortaddr, uint8_t index, uint16_t zdo_cmd) {
|
||||||
|
#ifdef USE_ZIGBEE_ZNP
|
||||||
|
SBuffer buf(10);
|
||||||
|
buf.add8(Z_SREQ | Z_ZDO); // 25
|
||||||
|
buf.add8(zdo_cmd); // 33
|
||||||
|
buf.add16(shortaddr); // shortaddr
|
||||||
|
buf.add8(index); // StartIndex = 0
|
||||||
|
|
||||||
|
ZigbeeZNPSend(buf.getBuffer(), buf.len());
|
||||||
|
#endif // USE_ZIGBEE_ZNP
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_ZIGBEE_EZSP
|
||||||
|
// ZDO message payload (see Zigbee spec 2.4.3.3.4)
|
||||||
|
uint8_t buf[] = { index }; // index = 0
|
||||||
|
|
||||||
|
EZ_SendZDO(shortaddr, zdo_cmd, buf, sizeof(buf), false);
|
||||||
|
#endif // USE_ZIGBEE_EZSP
|
||||||
|
}
|
||||||
|
|
||||||
|
// This callback is registered to send ZbMap(s) to each device one at a time
|
||||||
|
void Z_Map(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) {
|
||||||
|
if (BAD_SHORTADDR != shortaddr) {
|
||||||
|
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "sending `ZnMap 0x%04X`"), shortaddr);
|
||||||
|
#ifdef USE_ZIGBEE_ZNP
|
||||||
|
Z_Send_State_or_Map(shortaddr, value, ZDO_MGMT_LQI_REQ);
|
||||||
|
#endif // USE_ZIGBEE_ZNP
|
||||||
|
#ifdef USE_ZIGBEE_EZSP
|
||||||
|
Z_Send_State_or_Map(shortaddr, value, ZDO_Mgmt_Lqi_req);
|
||||||
|
#endif // USE_ZIGBEE_EZSP
|
||||||
|
} else {
|
||||||
|
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "ZbMap done"));
|
||||||
|
}
|
||||||
|
}
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Parsers for incoming EZSP messages
|
* Parsers for incoming EZSP messages
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
@ -948,80 +988,7 @@ int32_t Z_UnbindRsp(int32_t res, const class SBuffer &buf) {
|
|||||||
// Handle MgMt Bind Rsp incoming message
|
// Handle MgMt Bind Rsp incoming message
|
||||||
//
|
//
|
||||||
int32_t Z_MgmtBindRsp(int32_t res, const class SBuffer &buf) {
|
int32_t Z_MgmtBindRsp(int32_t res, const class SBuffer &buf) {
|
||||||
#ifdef USE_ZIGBEE_ZNP
|
return Z_Mgmt_Lqi_Bind_Rsp(res, buf, false);
|
||||||
uint16_t shortaddr = buf.get16(2);
|
|
||||||
uint8_t status = buf.get8(4);
|
|
||||||
uint8_t bind_total = buf.get8(5);
|
|
||||||
uint8_t bind_start = buf.get8(6);
|
|
||||||
uint8_t bind_len = buf.get8(7);
|
|
||||||
const size_t prefix_len = 8;
|
|
||||||
#endif // USE_ZIGBEE_ZNP
|
|
||||||
#ifdef USE_ZIGBEE_EZSP
|
|
||||||
uint16_t shortaddr = buf.get16(buf.len()-2);
|
|
||||||
uint8_t status = buf.get8(0);
|
|
||||||
uint8_t bind_total = buf.get8(1);
|
|
||||||
uint8_t bind_start = buf.get8(2);
|
|
||||||
uint8_t bind_len = buf.get8(3);
|
|
||||||
const size_t prefix_len = 4;
|
|
||||||
#endif // USE_ZIGBEE_EZSP
|
|
||||||
|
|
||||||
// device is reachable
|
|
||||||
zigbee_devices.deviceWasReached(shortaddr);
|
|
||||||
|
|
||||||
const char * friendlyName = zigbee_devices.getFriendlyName(shortaddr);
|
|
||||||
|
|
||||||
Response_P(PSTR("{\"" D_JSON_ZIGBEE_BIND_STATE "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), shortaddr);
|
|
||||||
if (friendlyName) {
|
|
||||||
ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""), friendlyName);
|
|
||||||
}
|
|
||||||
ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_STATUS "\":%d"
|
|
||||||
",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\""
|
|
||||||
",\"BindingsTotal\":%d"
|
|
||||||
",\"BindingsStart\":%d"
|
|
||||||
",\"Bindings\":["
|
|
||||||
), status, getZigbeeStatusMessage(status).c_str(), bind_total, bind_start + 1);
|
|
||||||
|
|
||||||
uint32_t idx = prefix_len;
|
|
||||||
for (uint32_t i = 0; i < bind_len; i++) {
|
|
||||||
if (idx + 14 > buf.len()) { break; } // overflow, frame size is between 14 and 21
|
|
||||||
|
|
||||||
//uint64_t srcaddr = buf.get16(idx); // unused
|
|
||||||
uint8_t srcep = buf.get8(idx + 8);
|
|
||||||
uint16_t cluster = buf.get16(idx + 9);
|
|
||||||
uint8_t addrmode = buf.get8(idx + 11);
|
|
||||||
uint16_t group = 0x0000;
|
|
||||||
uint64_t dstaddr = 0;
|
|
||||||
uint8_t dstep = 0x00;
|
|
||||||
if (Z_Addr_Group == addrmode) { // Group address mode
|
|
||||||
group = buf.get16(idx + 12);
|
|
||||||
idx += 14;
|
|
||||||
} else if (Z_Addr_IEEEAddress == addrmode) { // IEEE address mode
|
|
||||||
dstaddr = buf.get64(idx + 12);
|
|
||||||
dstep = buf.get8(idx + 20);
|
|
||||||
idx += 21;
|
|
||||||
} else {
|
|
||||||
//AddLog_P(LOG_LEVEL_INFO, PSTR("ZNP_MgmtBindRsp unknwon address mode %d"), addrmode);
|
|
||||||
break; // abort for any other value since we don't know the length of the field
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i > 0) {
|
|
||||||
ResponseAppend_P(PSTR(","));
|
|
||||||
}
|
|
||||||
ResponseAppend_P(PSTR("{\"Cluster\":\"0x%04X\",\"Endpoint\":%d,"), cluster, srcep);
|
|
||||||
if (Z_Addr_Group == addrmode) { // Group address mode
|
|
||||||
ResponseAppend_P(PSTR("\"ToGroup\":%d}"), group);
|
|
||||||
} else if (Z_Addr_IEEEAddress == addrmode) { // IEEE address mode
|
|
||||||
char hex[20];
|
|
||||||
Uint64toHex(dstaddr, hex, 64);
|
|
||||||
ResponseAppend_P(PSTR("\"ToDevice\":\"0x%s\",\"ToEndpoint\":%d}"), hex, dstep);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ResponseAppend_P(PSTR("]}}"));
|
|
||||||
|
|
||||||
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_BIND_STATE));
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return false, true or null (if unknown)
|
// Return false, true or null (if unknown)
|
||||||
@ -1056,23 +1023,25 @@ const char * Z_DeviceType(uint32_t value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Handle MgMt Bind Rsp incoming message
|
// Combined code for MgmtLqiRsp and MgmtBindRsp
|
||||||
//
|
//
|
||||||
int32_t Z_MgmtLqiRsp(int32_t res, const class SBuffer &buf) {
|
// If the response has a follow-up, send more requests automatically
|
||||||
|
//
|
||||||
|
int32_t Z_Mgmt_Lqi_Bind_Rsp(int32_t res, const class SBuffer &buf, boolean lqi) {
|
||||||
#ifdef USE_ZIGBEE_ZNP
|
#ifdef USE_ZIGBEE_ZNP
|
||||||
uint16_t shortaddr = buf.get16(2);
|
uint16_t shortaddr = buf.get16(2);
|
||||||
uint8_t status = buf.get8(4);
|
uint8_t status = buf.get8(4);
|
||||||
uint8_t lqi_total = buf.get8(5);
|
uint8_t total = buf.get8(5);
|
||||||
uint8_t lqi_start = buf.get8(6);
|
uint8_t start = buf.get8(6);
|
||||||
uint8_t lqi_len = buf.get8(7);
|
uint8_t len = buf.get8(7);
|
||||||
const size_t prefix_len = 8;
|
const size_t prefix_len = 8;
|
||||||
#endif // USE_ZIGBEE_ZNP
|
#endif // USE_ZIGBEE_ZNP
|
||||||
#ifdef USE_ZIGBEE_EZSP
|
#ifdef USE_ZIGBEE_EZSP
|
||||||
uint16_t shortaddr = buf.get16(buf.len()-2);
|
uint16_t shortaddr = buf.get16(buf.len()-2);
|
||||||
uint8_t status = buf.get8(0);
|
uint8_t status = buf.get8(0);
|
||||||
uint8_t lqi_total = buf.get8(1);
|
uint8_t total = buf.get8(1);
|
||||||
uint8_t lqi_start = buf.get8(2);
|
uint8_t start = buf.get8(2);
|
||||||
uint8_t lqi_len = buf.get8(3);
|
uint8_t len = buf.get8(3);
|
||||||
const size_t prefix_len = 4;
|
const size_t prefix_len = 4;
|
||||||
#endif // USE_ZIGBEE_EZSP
|
#endif // USE_ZIGBEE_EZSP
|
||||||
|
|
||||||
@ -1081,62 +1050,123 @@ int32_t Z_MgmtLqiRsp(int32_t res, const class SBuffer &buf) {
|
|||||||
|
|
||||||
const char * friendlyName = zigbee_devices.getFriendlyName(shortaddr);
|
const char * friendlyName = zigbee_devices.getFriendlyName(shortaddr);
|
||||||
|
|
||||||
Response_P(PSTR("{\"" D_JSON_ZIGBEE_MAP "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), shortaddr);
|
Response_P(PSTR("{\"%s\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""),
|
||||||
|
lqi ? PSTR(D_JSON_ZIGBEE_MAP) : PSTR(D_JSON_ZIGBEE_BIND_STATE), shortaddr);
|
||||||
if (friendlyName) {
|
if (friendlyName) {
|
||||||
ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""), friendlyName);
|
ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""), friendlyName);
|
||||||
}
|
}
|
||||||
ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_STATUS "\":%d"
|
ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_STATUS "\":%d"
|
||||||
",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\""
|
",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\""
|
||||||
",\"MapTotal\":%d"
|
",\"Total\":%d"
|
||||||
",\"MapStart\":%d"
|
",\"Start\":%d"
|
||||||
",\"Map\":["
|
",\"%s\":["
|
||||||
), status, getZigbeeStatusMessage(status).c_str(), lqi_total, lqi_start + 1);
|
), status, getZigbeeStatusMessage(status).c_str(), total, start + 1,
|
||||||
|
lqi ? PSTR("Map") : PSTR("Bindings"));
|
||||||
|
|
||||||
uint32_t idx = prefix_len;
|
if (lqi) {
|
||||||
for (uint32_t i = 0; i < lqi_len; i++) {
|
uint32_t idx = prefix_len;
|
||||||
if (idx + 22 > buf.len()) { break; } // size 22 for EZSP
|
for (uint32_t i = 0; i < len; i++) {
|
||||||
|
if (idx + 22 > buf.len()) { break; } // size 22 for EZSP
|
||||||
|
|
||||||
//uint64_t extpanid = buf.get16(idx); // unused
|
//uint64_t extpanid = buf.get16(idx); // unused
|
||||||
// uint64_t m_longaddr = buf.get64(idx + 8);
|
// uint64_t m_longaddr = buf.get64(idx + 8);
|
||||||
uint16_t m_shortaddr = buf.get16(idx + 16);
|
uint16_t m_shortaddr = buf.get16(idx + 16);
|
||||||
uint8_t m_dev_type = buf.get8(idx + 18);
|
uint8_t m_dev_type = buf.get8(idx + 18);
|
||||||
uint8_t m_permitjoin = buf.get8(idx + 19);
|
uint8_t m_permitjoin = buf.get8(idx + 19);
|
||||||
uint8_t m_depth = buf.get8(idx + 20);
|
uint8_t m_depth = buf.get8(idx + 20);
|
||||||
uint8_t m_lqi = buf.get8(idx + 21);
|
uint8_t m_lqi = buf.get8(idx + 21);
|
||||||
idx += 22;
|
idx += 22;
|
||||||
|
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
ResponseAppend_P(PSTR(","));
|
ResponseAppend_P(PSTR(","));
|
||||||
|
}
|
||||||
|
ResponseAppend_P(PSTR("{\"Device\":\"0x%04X\","), m_shortaddr);
|
||||||
|
|
||||||
|
const char * friendlyName = zigbee_devices.getFriendlyName(m_shortaddr);
|
||||||
|
if (friendlyName) {
|
||||||
|
ResponseAppend_P(PSTR("\"Name\":\"%s\","), friendlyName);
|
||||||
|
}
|
||||||
|
ResponseAppend_P(PSTR("\"DeviceType\":\"%s\","
|
||||||
|
"\"RxOnWhenIdle\":%s,"
|
||||||
|
"\"Relationship\":\"%s\","
|
||||||
|
"\"PermitJoin\":%s,"
|
||||||
|
"\"Depth\":%d,"
|
||||||
|
"\"LinkQuality\":%d"
|
||||||
|
"}"
|
||||||
|
),
|
||||||
|
Z_DeviceType(m_dev_type & 0x03),
|
||||||
|
TrueFalseNull((m_dev_type & 0x0C) >> 2),
|
||||||
|
Z_DeviceRelationship((m_dev_type & 0x70) >> 4),
|
||||||
|
TrueFalseNull(m_permitjoin & 0x02),
|
||||||
|
m_depth,
|
||||||
|
m_lqi);
|
||||||
}
|
}
|
||||||
ResponseAppend_P(PSTR("{\"Device\":\"0x%04X\","), m_shortaddr);
|
|
||||||
|
|
||||||
const char * friendlyName = zigbee_devices.getFriendlyName(m_shortaddr);
|
ResponseAppend_P(PSTR("]}}"));
|
||||||
if (friendlyName) {
|
} else { // Bind
|
||||||
ResponseAppend_P(PSTR("\"Name\":\"%s\","), friendlyName);
|
|
||||||
|
uint32_t idx = prefix_len;
|
||||||
|
for (uint32_t i = 0; i < len; i++) {
|
||||||
|
if (idx + 14 > buf.len()) { break; } // overflow, frame size is between 14 and 21
|
||||||
|
|
||||||
|
//uint64_t srcaddr = buf.get16(idx); // unused
|
||||||
|
uint8_t srcep = buf.get8(idx + 8);
|
||||||
|
uint16_t cluster = buf.get16(idx + 9);
|
||||||
|
uint8_t addrmode = buf.get8(idx + 11);
|
||||||
|
uint16_t group = 0x0000;
|
||||||
|
uint64_t dstaddr = 0;
|
||||||
|
uint8_t dstep = 0x00;
|
||||||
|
if (Z_Addr_Group == addrmode) { // Group address mode
|
||||||
|
group = buf.get16(idx + 12);
|
||||||
|
idx += 14;
|
||||||
|
} else if (Z_Addr_IEEEAddress == addrmode) { // IEEE address mode
|
||||||
|
dstaddr = buf.get64(idx + 12);
|
||||||
|
dstep = buf.get8(idx + 20);
|
||||||
|
idx += 21;
|
||||||
|
} else {
|
||||||
|
//AddLog_P(LOG_LEVEL_INFO, PSTR("ZNP_MgmtBindRsp unknwon address mode %d"), addrmode);
|
||||||
|
break; // abort for any other value since we don't know the length of the field
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > 0) {
|
||||||
|
ResponseAppend_P(PSTR(","));
|
||||||
|
}
|
||||||
|
ResponseAppend_P(PSTR("{\"Cluster\":\"0x%04X\",\"Endpoint\":%d,"), cluster, srcep);
|
||||||
|
if (Z_Addr_Group == addrmode) { // Group address mode
|
||||||
|
ResponseAppend_P(PSTR("\"ToGroup\":%d}"), group);
|
||||||
|
} else if (Z_Addr_IEEEAddress == addrmode) { // IEEE address mode
|
||||||
|
char hex[20];
|
||||||
|
Uint64toHex(dstaddr, hex, 64);
|
||||||
|
ResponseAppend_P(PSTR("\"ToDevice\":\"0x%s\",\"ToEndpoint\":%d}"), hex, dstep);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ResponseAppend_P(PSTR("\"DeviceType\":\"%s\","
|
|
||||||
"\"RxOnWhenIdle\":%s,"
|
ResponseAppend_P(PSTR("]}}"));
|
||||||
"\"Relationship\":\"%s\","
|
|
||||||
"\"PermitJoin\":%s,"
|
|
||||||
"\"Depth\":%d,"
|
|
||||||
"\"LinkQuality\":%d"
|
|
||||||
"}"
|
|
||||||
),
|
|
||||||
Z_DeviceType(m_dev_type & 0x03),
|
|
||||||
TrueFalseNull((m_dev_type & 0x0C) >> 2),
|
|
||||||
Z_DeviceRelationship((m_dev_type & 0x70) >> 4),
|
|
||||||
TrueFalseNull(m_permitjoin & 0x02),
|
|
||||||
m_depth,
|
|
||||||
m_lqi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResponseAppend_P(PSTR("]}}"));
|
|
||||||
|
|
||||||
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_MAP));
|
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_MAP));
|
||||||
|
|
||||||
|
// Check if there are more values waiting, if so re-send a new request to get other values
|
||||||
|
if (start + len < total) {
|
||||||
|
// there are more values to read
|
||||||
|
#ifdef USE_ZIGBEE_ZNP
|
||||||
|
Z_Send_State_or_Map(shortaddr, start + len, lqi ? ZDO_MGMT_LQI_REQ : ZDO_MGMT_BIND_REQ);
|
||||||
|
#endif // USE_ZIGBEE_ZNP
|
||||||
|
#ifdef USE_ZIGBEE_EZSP
|
||||||
|
Z_Send_State_or_Map(shortaddr, start + len, lqi ? ZDO_Mgmt_Lqi_req : ZDO_Mgmt_Bind_req);
|
||||||
|
#endif // USE_ZIGBEE_EZSP
|
||||||
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Handle MgMt Bind Rsp incoming message
|
||||||
|
//
|
||||||
|
int32_t Z_MgmtLqiRsp(int32_t res, const class SBuffer &buf) {
|
||||||
|
return Z_Mgmt_Lqi_Bind_Rsp(res, buf, true);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_ZIGBEE_EZSP
|
#ifdef USE_ZIGBEE_EZSP
|
||||||
//
|
//
|
||||||
// Handle Parent Annonce Rsp incoming message
|
// Handle Parent Annonce Rsp incoming message
|
||||||
@ -1572,7 +1602,7 @@ void Z_IncomingMessage(class ZCLFrame &zcl_received) {
|
|||||||
* Send ZDO Message
|
* Send ZDO Message
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
void EZ_SendZDO(uint16_t shortaddr, uint16_t cmd, const unsigned char *payload, size_t payload_len) {
|
void EZ_SendZDO(uint16_t shortaddr, uint16_t cmd, const unsigned char *payload, size_t payload_len, bool retry) {
|
||||||
SBuffer buf(payload_len + 22);
|
SBuffer buf(payload_len + 22);
|
||||||
uint8_t seq = zigbee_devices.getNextSeqNumber(0x0000);
|
uint8_t seq = zigbee_devices.getNextSeqNumber(0x0000);
|
||||||
|
|
||||||
@ -1587,7 +1617,11 @@ void EZ_SendZDO(uint16_t shortaddr, uint16_t cmd, const unsigned char *payload,
|
|||||||
buf.add16(cmd); // ZDO cmd in cluster
|
buf.add16(cmd); // ZDO cmd in cluster
|
||||||
buf.add8(0); // srcEp
|
buf.add8(0); // srcEp
|
||||||
buf.add8(0); // dstEp
|
buf.add8(0); // dstEp
|
||||||
buf.add16(EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY | EMBER_APS_OPTION_RETRY); // APS frame
|
if (retry) {
|
||||||
|
buf.add16(EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY | EMBER_APS_OPTION_RETRY); // APS frame
|
||||||
|
} else {
|
||||||
|
buf.add16(EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY); // APS frame
|
||||||
|
}
|
||||||
buf.add16(0x0000); // groupId
|
buf.add16(0x0000); // groupId
|
||||||
buf.add8(seq);
|
buf.add8(seq);
|
||||||
// end of ApsFrame
|
// end of ApsFrame
|
||||||
|
@ -986,24 +986,7 @@ void CmndZbBindState_or_Map(uint16_t zdo_cmd) {
|
|||||||
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||||
uint8_t index = XdrvMailbox.index - 1; // change default 1 to 0
|
uint8_t index = XdrvMailbox.index - 1; // change default 1 to 0
|
||||||
|
|
||||||
#ifdef USE_ZIGBEE_ZNP
|
Z_Send_State_or_Map(shortaddr, index, zdo_cmd);
|
||||||
SBuffer buf(10);
|
|
||||||
buf.add8(Z_SREQ | Z_ZDO); // 25
|
|
||||||
buf.add8(zdo_cmd); // 33
|
|
||||||
buf.add16(shortaddr); // shortaddr
|
|
||||||
buf.add8(index); // StartIndex = 0
|
|
||||||
|
|
||||||
ZigbeeZNPSend(buf.getBuffer(), buf.len());
|
|
||||||
#endif // USE_ZIGBEE_ZNP
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_ZIGBEE_EZSP
|
|
||||||
// ZDO message payload (see Zigbee spec 2.4.3.3.4)
|
|
||||||
uint8_t buf[] = { index }; // index = 0
|
|
||||||
|
|
||||||
EZ_SendZDO(shortaddr, zdo_cmd, buf, sizeof(buf));
|
|
||||||
#endif // USE_ZIGBEE_EZSP
|
|
||||||
|
|
||||||
ResponseCmndDone();
|
ResponseCmndDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1025,12 +1008,28 @@ void CmndZbBindState(void) {
|
|||||||
// `ZbMap<x>` as index if it does not fit. If default, `1` starts at the beginning
|
// `ZbMap<x>` as index if it does not fit. If default, `1` starts at the beginning
|
||||||
//
|
//
|
||||||
void CmndZbMap(void) {
|
void CmndZbMap(void) {
|
||||||
|
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||||
|
RemoveSpace(XdrvMailbox.data);
|
||||||
|
|
||||||
|
if (strlen(XdrvMailbox.data) == 0) {
|
||||||
|
// defer sending ZbMap to each device
|
||||||
|
const static uint32_t DELAY_ZBMAP = 2000; // wait for 1s between commands
|
||||||
|
uint32_t wait_ms = DELAY_ZBMAP;
|
||||||
|
zigbee_devices.setTimer(0x0000, 0, 0 /*wait_ms*/, 0, 0, Z_CAT_ALWAYS, 0 /* value = index */, &Z_Map);
|
||||||
|
for (const auto & device : zigbee_devices.getDevices()) {
|
||||||
|
zigbee_devices.setTimer(device.shortaddr, 0, wait_ms, 0, 0, Z_CAT_ALWAYS, 0 /* value = index */, &Z_Map);
|
||||||
|
wait_ms += DELAY_ZBMAP;
|
||||||
|
}
|
||||||
|
zigbee_devices.setTimer(BAD_SHORTADDR, 0, wait_ms, 0, 0, Z_CAT_ALWAYS, 0 /* value = index */, &Z_Map);
|
||||||
|
ResponseCmndDone();
|
||||||
|
} else {
|
||||||
#ifdef USE_ZIGBEE_ZNP
|
#ifdef USE_ZIGBEE_ZNP
|
||||||
CmndZbBindState_or_Map(ZDO_MGMT_LQI_REQ);
|
CmndZbBindState_or_Map(ZDO_MGMT_LQI_REQ);
|
||||||
#endif // USE_ZIGBEE_ZNP
|
#endif // USE_ZIGBEE_ZNP
|
||||||
#ifdef USE_ZIGBEE_EZSP
|
#ifdef USE_ZIGBEE_EZSP
|
||||||
CmndZbBindState_or_Map(ZDO_Mgmt_Lqi_req);
|
CmndZbBindState_or_Map(ZDO_Mgmt_Lqi_req);
|
||||||
#endif // USE_ZIGBEE_EZSP
|
#endif // USE_ZIGBEE_EZSP
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Probe a specific device to get its endpoints and supported clusters
|
// Probe a specific device to get its endpoints and supported clusters
|
||||||
|
Loading…
x
Reference in New Issue
Block a user