Merge pull request #8469 from s-hadinger/zigbee_non_zero_addr2

Zigbee allow zero shortaddr
This commit is contained in:
Theo Arends 2020-05-17 19:22:44 +02:00 committed by GitHub
commit b797a2ce1f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 101 additions and 189 deletions

View File

@ -24,6 +24,8 @@
typedef uint64_t Z_IEEEAddress;
typedef uint16_t Z_ShortAddress;
const uint16_t BAD_SHORTADDR = 0xFFFE;
enum ZnpCommandType {
Z_POLL = 0x00,
Z_SREQ = 0x20,

View File

@ -103,7 +103,7 @@ public:
// Probe the existence of device keys
// Results:
// - 0x0000 = not found
// - 0xFFFF = bad parameter
// - BAD_SHORTADDR = bad parameter
// - 0x<shortaddr> = the device's short address
uint16_t isKnownShortAddr(uint16_t shortaddr) const;
uint16_t isKnownLongAddr(uint64_t longaddr) const;
@ -295,18 +295,16 @@ void Z_Devices::freeDeviceEntry(Z_Device *device) {
// Scan all devices to find a corresponding shortaddr
// Looks info device.shortaddr entry
// In:
// shortaddr (non null)
// shortaddr (not BAD_SHORTADDR)
// Out:
// index in _devices of entry, -1 if not found
//
int32_t Z_Devices::findShortAddr(uint16_t shortaddr) const {
if (!shortaddr) { return -1; } // does not make sense to look for 0x0000 shortaddr (localhost)
if (BAD_SHORTADDR == shortaddr) { return -1; } // does not make sense to look for BAD_SHORTADDR shortaddr (broadcast)
int32_t found = 0;
if (shortaddr) {
for (auto &elem : _devices) {
if (elem->shortaddr == shortaddr) { return found; }
found++;
}
for (auto &elem : _devices) {
if (elem->shortaddr == shortaddr) { return found; }
found++;
}
return -1;
}
@ -321,11 +319,9 @@ int32_t Z_Devices::findShortAddr(uint16_t shortaddr) const {
int32_t Z_Devices::findLongAddr(uint64_t longaddr) const {
if (!longaddr) { return -1; }
int32_t found = 0;
if (longaddr) {
for (auto &elem : _devices) {
if (elem->longaddr == longaddr) { return found; }
found++;
}
for (auto &elem : _devices) {
if (elem->longaddr == longaddr) { return found; }
found++;
}
return -1;
}
@ -358,7 +354,7 @@ uint16_t Z_Devices::isKnownShortAddr(uint16_t shortaddr) const {
if (found >= 0) {
return shortaddr;
} else {
return 0; // unknown
return BAD_SHORTADDR; // unknown
}
}
@ -368,7 +364,7 @@ uint16_t Z_Devices::isKnownLongAddr(uint64_t longaddr) const {
const Z_Device & device = devicesAt(found);
return device.shortaddr; // can be zero, if not yet registered
} else {
return 0;
return BAD_SHORTADDR;
}
}
@ -377,18 +373,18 @@ uint16_t Z_Devices::isKnownIndex(uint32_t index) const {
const Z_Device & device = devicesAt(index);
return device.shortaddr;
} else {
return 0;
return BAD_SHORTADDR;
}
}
uint16_t Z_Devices::isKnownFriendlyName(const char * name) const {
if ((!name) || (0 == strlen(name))) { return 0xFFFF; } // Error
if ((!name) || (0 == strlen(name))) { return BAD_SHORTADDR; } // Error
int32_t found = findFriendlyName(name);
if (found >= 0) {
const Z_Device & device = devicesAt(found);
return device.shortaddr; // can be zero, if not yet registered
} else {
return 0;
return BAD_SHORTADDR;
}
}
@ -398,10 +394,10 @@ uint64_t Z_Devices::getDeviceLongAddr(uint16_t shortaddr) const {
}
//
// We have a seen a shortaddr on the network, get the corresponding
// We have a seen a shortaddr on the network, get the corresponding device object
//
Z_Device & Z_Devices::getShortAddr(uint16_t shortaddr) {
if (!shortaddr) { return *(Z_Device*) nullptr; } // this is not legal
if (BAD_SHORTADDR == shortaddr) { return *(Z_Device*) nullptr; } // this is not legal
int32_t found = findShortAddr(shortaddr);
if (found >= 0) {
return *(_devices[found]);
@ -411,7 +407,7 @@ Z_Device & Z_Devices::getShortAddr(uint16_t shortaddr) {
}
// Same version but Const
const Z_Device & Z_Devices::getShortAddrConst(uint16_t shortaddr) const {
if (!shortaddr) { return *(Z_Device*) nullptr; } // this is not legal
if (BAD_SHORTADDR == shortaddr) { return *(Z_Device*) nullptr; } // this is not legal
int32_t found = findShortAddr(shortaddr);
if (found >= 0) {
return *(_devices[found]);
@ -471,7 +467,7 @@ void Z_Devices::updateDevice(uint16_t shortaddr, uint64_t longaddr) {
dirty();
} else {
// neither short/lonf addr are found.
if (shortaddr || longaddr) {
if ((BAD_SHORTADDR != shortaddr) || longaddr) {
createDeviceEntry(shortaddr, longaddr);
}
}
@ -481,7 +477,6 @@ void Z_Devices::updateDevice(uint16_t shortaddr, uint64_t longaddr) {
// Clear all endpoints
//
void Z_Devices::clearEndpoints(uint16_t shortaddr) {
if (!shortaddr) { return; }
Z_Device &device = getShortAddr(shortaddr);
if (&device == nullptr) { return; } // don't crash if not found
@ -495,7 +490,6 @@ void Z_Devices::clearEndpoints(uint16_t shortaddr) {
// Add an endpoint to a shortaddr
//
void Z_Devices::addEndpoint(uint16_t shortaddr, uint8_t endpoint) {
if (!shortaddr) { return; }
if (0x00 == endpoint) { return; }
Z_Device &device = getShortAddr(shortaddr);
if (&device == nullptr) { return; } // don't crash if not found
@ -922,7 +916,7 @@ uint16_t Z_Devices::parseDeviceParam(const char * param, bool short_must_be_know
char dataBuf[param_len + 1];
strcpy(dataBuf, param);
RemoveSpace(dataBuf);
uint16_t shortaddr = 0;
uint16_t shortaddr = BAD_SHORTADDR; // start with unknown
if (strlen(dataBuf) < 4) {
// simple number 0..99
@ -1018,8 +1012,8 @@ String Z_Devices::dump(uint32_t dump_mode, uint16_t status_shortaddr) const {
uint16_t shortaddr = device.shortaddr;
char hex[22];
// ignore non-current device, if specified device is non-zero
if ((status_shortaddr) && (status_shortaddr != shortaddr)) { continue; }
// ignore non-current device, if device specified
if ((BAD_SHORTADDR != status_shortaddr) && (status_shortaddr != shortaddr)) { continue; }
JsonObject& dev = devices.createNestedObject();

View File

@ -66,41 +66,6 @@ public:
const static uint32_t ZIGB_NAME = 0x3167697A; // 'zig1' little endian
const static size_t Z_MAX_FLASH = z_block_len - sizeof(z_flashdata_t); // 2040
// encoding for the most commonly 32 clusters, used for binary encoding
const uint16_t Z_ClusterNumber[] PROGMEM = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
0x0100, 0x0101, 0x0102,
0x0201, 0x0202, 0x0203, 0x0204,
0x0300, 0x0301,
0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406,
0x0500, 0x0501, 0x0502,
0x0700, 0x0701, 0x0702,
0x0B00, 0x0B01, 0x0B02, 0x0B03, 0x0B04, 0x0B05,
0x1000,
0xFC0F,
};
// convert a 1 byte cluster code to the actual cluster number
uint16_t fromClusterCode(uint8_t c) {
if (c >= ARRAY_SIZE(Z_ClusterNumber)) {
return 0xFFFF; // invalid
}
return pgm_read_word(&Z_ClusterNumber[c]);
}
// convert a cluster number to 1 byte, or 0xFF if not in table
uint8_t toClusterCode(uint16_t c) {
for (uint32_t i = 0; i < ARRAY_SIZE(Z_ClusterNumber); i++) {
if (c == pgm_read_word(&Z_ClusterNumber[i])) {
return i;
}
}
return 0xFF; // not found
}
class SBuffer hibernateDevice(const struct Z_Device &device) {
SBuffer buf(128);
@ -202,18 +167,8 @@ void hydrateDevices(const SBuffer &buf) {
for (uint32_t i = 0; (i < num_devices) && (k < buf_len); i++) {
uint32_t dev_record_len = buf.get8(k);
// AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Device %d Before Memory = %d // DIFF %d // record_len %d"), i, ESP_getFreeHeap(), before - ESP_getFreeHeap(), dev_record_len);
// before = ESP_getFreeHeap();
SBuffer buf_d = buf.subBuffer(k, dev_record_len);
// char *hex_char = (char*) malloc((dev_record_len * 2) + 2);
// if (hex_char) {
// AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "/// SUB %s"),
// ToHex_P(buf_d.getBuffer(), dev_record_len, hex_char, (dev_record_len * 2) + 2));
// free(hex_char);
// }
uint32_t d = 1; // index in device buffer
uint16_t shortaddr = buf_d.get16(d); d += 2;
uint64_t longaddr = buf_d.get64(d); d += 8;

View File

@ -79,16 +79,6 @@ uint8_t Z_getDatatypeLen(uint8_t t) {
}
}
// typedef struct Z_DataTypeMapping {
// uint8_t datatype;
// uint8_t len; // len in bytes and add 0x80 if DISCRETE
// }
// const Z_DataTypeMapping Z_types[] PROGMEM = {
// { Znodata, 0 },
// { Zdata8, 0 },
// };
typedef union ZCLHeaderFrameControl_t {
struct {
uint8_t frame_type : 2; // 00 = across entire profile, 01 = cluster specific
@ -572,6 +562,9 @@ typedef struct Z_AttributeConverter {
Z_AttrConverter func;
} Z_AttributeConverter;
// Cluster numbers are store in 8 bits format to save space,
// the following tables allows the conversion from 8 bits index Cx...
// to the 16 bits actual cluster number
enum Cx_cluster_short {
Cx0000, Cx0001, Cx0002, Cx0003, Cx0004, Cx0005, Cx0006, Cx0007,
Cx0008, Cx0009, Cx000A, Cx000B, Cx000C, Cx000D, Cx000E, Cx000F,

View File

@ -177,6 +177,9 @@ int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t clus
break;
}
if (attrs) {
if (groupaddr) {
shortaddr = BAD_SHORTADDR; // if group address, don't send to device
}
ZigbeeZCLSend_Raw(shortaddr, groupaddr, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, 0, attrs, attrs_len, true /* we do want a response */, zigbee_devices.getNextSeqNumber(shortaddr));
}
}
@ -184,7 +187,7 @@ int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t clus
// This callback is registered after a an attribute read command was made to a light, and fires if we don't get any response after 1000 ms
int32_t Z_Unreachable(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) {
if (shortaddr) {
if (BAD_SHORTADDR != shortaddr) {
zigbee_devices.setReachable(shortaddr, false); // mark device as reachable
}
}
@ -208,7 +211,7 @@ void zigbeeSetCommandTimer(uint16_t shortaddr, uint16_t groupaddr, uint16_t clus
}
if (wait_ms) {
zigbee_devices.setTimer(shortaddr, groupaddr, wait_ms, cluster, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback);
if (shortaddr) { // reachability test is not possible for group addresses, since we don't know the list of devices in the group
if (BAD_SHORTADDR != shortaddr) { // reachability test is not possible for group addresses, since we don't know the list of devices in the group
zigbee_devices.setTimer(shortaddr, groupaddr, wait_ms + Z_CAT_REACHABILITY_TIMEOUT, cluster, endpoint, Z_CAT_REACHABILITY, 0 /* value */, &Z_Unreachable);
}
}
@ -314,12 +317,12 @@ void sendHueUpdate(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uin
}
if (z_cat >= 0) {
uint8_t endpoint = 0;
if (shortaddr) {
if (BAD_SHORTADDR != shortaddr) {
endpoint = zigbee_devices.findFirstEndpoint(shortaddr);
}
if ((!shortaddr) || (endpoint)) { // send if group address or endpoint is known
if ((BAD_SHORTADDR == shortaddr) || (endpoint)) { // send if group address or endpoint is known
zigbee_devices.setTimer(shortaddr, groupaddr, wait_ms, cluster, endpoint, z_cat, 0 /* value */, &Z_ReadAttrCallback);
if (shortaddr) { // reachability test is not possible for group addresses, since we don't know the list of devices in the group
if (BAD_SHORTADDR != shortaddr) { // reachability test is not possible for group addresses, since we don't know the list of devices in the group
zigbee_devices.setTimer(shortaddr, groupaddr, wait_ms + Z_CAT_REACHABILITY_TIMEOUT, cluster, endpoint, Z_CAT_REACHABILITY, 0 /* value */, &Z_Unreachable);
}

View File

@ -584,18 +584,6 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
ZI_WAIT_RECV(1000, ZBS_LOGTYPE_DEVICE) // it should be coordinator
ZI_GOTO(ZIGBEE_LABEL_START_ROUTER)
// Device and Router code is common from now
// ZI_LABEL(ZIGBEE_LABEL_START_DEVICE) // Init as a router
// ZI_MQTT_STATE(ZIGBEE_STATUS_STARTING, kConfiguredDevice)
// ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT)
// ZI_SEND(ZBS_AF_REGISTER_ALL) // Z_AF register for endpoint 01, profile 0x0104 Home Automation
// ZI_WAIT_RECV(1000, ZBR_AF_REGISTER)
// ZI_SEND(ZBS_STARTUPFROMAPP) // start router
// ZI_WAIT_RECV(2000, ZBR_STARTUPFROMAPP) // wait for sync ack of command
// ZI_WAIT_UNTIL_FUNC(0xFFFF, AREQ_STARTUPFROMAPP, &Z_ReceiveStateChange) // wait forever for async message that coordinator started
// ZI_SEND(ZBS_GETDEVICEINFO) // GetDeviceInfo
// ZI_WAIT_RECV_FUNC(2000, ZBR_GETDEVICEINFO, &Z_ReceiveDeviceInfo)
// ZI_GOTO(ZIGBEE_LABEL_READY)
ZI_LABEL(ZIGBEE_LABEL_FACT_RESET_DEVICE) // Factory reset for router
ZI_MQTT_STATE(ZIGBEE_STATUS_RESET_CONF, kResetting)
@ -608,25 +596,12 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
ZI_WAIT_RECV(1000, ZBR_W_OK)
ZI_GOTO(ZIGBEE_LABEL_FACT_RESET_ROUTER_DEVICE_POST)
// ZI_SEND(ZBS_W_ALL_PAN) // write universal PAN ID = 0xFFFF
// ZI_WAIT_RECV(1000, ZBR_W_OK)
// ZI_SEND(ZBS_W_ALL_CHANN) // write Allows all CHANNELS = 0x07FFF800, 11-26
// ZI_WAIT_RECV(1000, ZBR_W_OK)
// // Now mark the device as ready, writing 0x55 in memory slot 0x0F00
// ZI_SEND(ZBS_WNV_INITZNPHC) // Init NV ZNP Has Configured
// ZI_WAIT_RECV_FUNC(1000, ZBR_WNV_INIT_OK, &Z_CheckNVWrite)
// ZI_SEND(ZBS_WNV_ZNPHC) // Write NV ZNP Has Configured
// ZI_WAIT_RECV(1000, ZBR_WNV_OK)
// ZI_GOTO(ZIGBEE_LABEL_START_ROUTER)
// ZI_GOTO(ZIGBEE_LABEL_START_DEVICE)
// Error: version of Z-Stack is not supported
ZI_LABEL(ZIGBEE_LABEL_UNSUPPORTED_VERSION)
ZI_MQTT_STATE(ZIGBEE_STATUS_UNSUPPORTED_VERSION, kZNP12)
ZI_GOTO(ZIGBEE_LABEL_ABORT)
// Abort state machine, general error
ZI_LABEL(ZIGBEE_LABEL_ABORT) // Label 99: abort
ZI_MQTT_STATE(ZIGBEE_STATUS_ABORT, kAbort)
ZI_LOG(LOG_LEVEL_ERROR, kZigbeeAbort)

View File

@ -52,7 +52,7 @@ int32_t Z_ReceiveDeviceInfo(int32_t res, class SBuffer &buf) {
ZIGBEE_STATUS_CC_INFO, hex, short_adr, device_type, device_state,
device_associated);
if (device_associated > 0) {
if (device_associated > 0) { // If there are devices registered in CC2530, print the list
uint idx = 16;
ResponseAppend_P(PSTR(",\"AssocDevicesList\":["));
for (uint32_t i = 0; i < device_associated; i++) {
@ -87,18 +87,20 @@ int32_t Z_Reboot(int32_t res, class SBuffer &buf) {
// print information about the reboot of device
// 4180.02.02.00.02.06.03
//
static const char Z_RebootReason[] PROGMEM = "Power-up|External|Watchdog";
uint8_t reason = buf.get8(2);
uint8_t transport_rev = buf.get8(3);
uint8_t product_id = buf.get8(4);
uint8_t major_rel = buf.get8(5);
uint8_t minor_rel = buf.get8(6);
uint8_t hw_rev = buf.get8(7);
char reason_str[12];
const char *reason_str;
if (reason > 3) { reason = 3; }
GetTextIndexed(reason_str, sizeof(reason_str), reason, Z_RebootReason);
switch (reason) {
case 0: reason_str = PSTR("Power-up"); break;
case 1: reason_str = PSTR("External"); break;
case 2: reason_str = PSTR("Watchdog"); break;
default: reason_str = PSTR("Unknown"); break;
}
Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{"
"\"Status\":%d,\"Message\":\"CC2530 booted\",\"RestartReason\":\"%s\""
@ -201,7 +203,6 @@ int32_t Z_ReceivePermitJoinStatus(int32_t res, const class SBuffer &buf) {
return -1;
}
const char* Z_DeviceType[] = { "Coordinator", "Router", "End Device", "Unknown" };
int32_t Z_ReceiveNodeDesc(int32_t res, const class SBuffer &buf) {
// Received ZDO_NODE_DESC_RSP
Z_ShortAddress srcAddr = buf.get16(2);
@ -217,15 +218,22 @@ int32_t Z_ReceiveNodeDesc(int32_t res, const class SBuffer &buf) {
uint16_t maxOutTransferSize = buf.get16(17);
uint8_t descriptorCapabilities = buf.get8(19);
if (0 == status) {
uint8_t deviceType = logicalType & 0x7; // 0=coordinator, 1=router, 2=end device
if (deviceType > 3) { deviceType = 3; }
const char * deviceTypeStr;
switch (deviceType) {
case 0: deviceTypeStr = PSTR("Coordinator"); break;
case 1: deviceTypeStr = PSTR("Router"); break;
case 2: deviceTypeStr = PSTR("Device"); break;
default: deviceTypeStr = PSTR("Unknown"); break;
}
bool complexDescriptorAvailable = (logicalType & 0x08) ? 1 : 0;
Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{"
"\"Status\":%d,\"NodeType\":\"%s\",\"ComplexDesc\":%s}}"),
ZIGBEE_STATUS_NODE_DESC, Z_DeviceType[deviceType],
complexDescriptorAvailable ? "true" : "false"
ZIGBEE_STATUS_NODE_DESC, deviceTypeStr,
complexDescriptorAvailable ? PSTR("true") : PSTR("false")
);
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED));
@ -282,15 +290,13 @@ int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf) {
Uint64toHex(ieeeAddr, hex, 64);
// Ping response
const char * friendlyName = zigbee_devices.getFriendlyName(nwkAddr);
Response_P(PSTR("{\"" D_JSON_ZIGBEE_PING "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""
",\"" D_JSON_ZIGBEE_IEEE "\":\"0x%s\""), nwkAddr, hex);
if (friendlyName) {
Response_P(PSTR("{\"" D_JSON_ZIGBEE_PING "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""
",\"" D_JSON_ZIGBEE_IEEE "\":\"0x%s\""
",\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), nwkAddr, hex, friendlyName);
} else {
Response_P(PSTR("{\"" D_JSON_ZIGBEE_PING "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""
",\"" D_JSON_ZIGBEE_IEEE "\":\"0x%s\""
"}}"), nwkAddr, hex);
ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""), friendlyName);
}
ResponseAppend_P(PSTR("\"}}"));
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED));
XdrvRulesProcess();
@ -398,9 +404,9 @@ int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) {
"\"Status\":%d,\"IEEEAddr\":\"0x%s\",\"ShortAddr\":\"0x%04X\""
",\"PowerSource\":%s,\"ReceiveWhenIdle\":%s,\"Security\":%s}}"),
ZIGBEE_STATUS_DEVICE_ANNOUNCE, hex, nwkAddr,
(capabilities & 0x04) ? "true" : "false",
(capabilities & 0x08) ? "true" : "false",
(capabilities & 0x40) ? "true" : "false"
(capabilities & 0x04) ? PSTR("true") : PSTR("false"),
(capabilities & 0x08) ? PSTR("true") : PSTR("false"),
(capabilities & 0x40) ? PSTR("true") : PSTR("false")
);
// query the state of the bulb (for Alexa)
uint32_t wait_ms = 2000; // wait for 2s
@ -444,18 +450,15 @@ int32_t Z_BindRsp(int32_t res, const class SBuffer &buf) {
uint8_t status = buf.get8(4);
const char * friendlyName = zigbee_devices.getFriendlyName(nwkAddr);
Response_P(PSTR("{\"" D_JSON_ZIGBEE_BIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), nwkAddr);
if (friendlyName) {
Response_P(PSTR("{\"" D_JSON_ZIGBEE_BIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""
",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""
",\"" D_JSON_ZIGBEE_STATUS "\":%d"
",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\""
"}}"), nwkAddr, friendlyName, status, getZigbeeStatusMessage(status).c_str());
} else {
Response_P(PSTR("{\"" D_JSON_ZIGBEE_BIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""
",\"" D_JSON_ZIGBEE_STATUS "\":%d"
",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\""
"}}"), nwkAddr, status, getZigbeeStatusMessage(status).c_str());
ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""), friendlyName);
}
ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_STATUS "\":%d"
",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\""
"}}"), status, getZigbeeStatusMessage(status).c_str());
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED));
XdrvRulesProcess();
@ -470,18 +473,14 @@ int32_t Z_UnbindRsp(int32_t res, const class SBuffer &buf) {
uint8_t status = buf.get8(4);
const char * friendlyName = zigbee_devices.getFriendlyName(nwkAddr);
Response_P(PSTR("{\"" D_JSON_ZIGBEE_UNBIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), nwkAddr);
if (friendlyName) {
Response_P(PSTR("{\"" D_JSON_ZIGBEE_UNBIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""
",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""
",\"" D_JSON_ZIGBEE_STATUS "\":%d"
",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\""
"}}"), nwkAddr, friendlyName, status, getZigbeeStatusMessage(status).c_str());
} else {
Response_P(PSTR("{\"" D_JSON_ZIGBEE_UNBIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""
",\"" D_JSON_ZIGBEE_STATUS "\":%d"
",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\""
"}}"), nwkAddr, status, getZigbeeStatusMessage(status).c_str());
ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""), friendlyName);
}
ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\""
"}}"), status, getZigbeeStatusMessage(status).c_str());
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED));
XdrvRulesProcess();
@ -506,7 +505,6 @@ int32_t Z_MgmtBindRsp(int32_t res, const class SBuffer &buf) {
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);
@ -631,7 +629,7 @@ int32_t Z_PublishAttributes(uint16_t shortaddr, uint16_t groupaddr, uint16_t clu
int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) {
uint16_t groupid = buf.get16(2);
uint16_t clusterid = buf.get16(4);
Z_ShortAddress srcaddr = buf.get16(6);
uint16_t srcaddr = buf.get16(6);
uint8_t srcendpoint = buf.get8(8);
uint8_t dstendpoint = buf.get8(9);
uint8_t wasbroadcast = buf.get8(10);

View File

@ -147,7 +147,7 @@ void ZigbeeInputLoop(void)
// Initialize internal structures
void ZigbeeInit(void)
{
// Check if settings if Flash are set
// Check if settings in Flash are set
if (0 == Settings.zb_channel) {
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Initializing Zigbee parameters from defaults"));
Settings.zb_ext_panid = USE_ZIGBEE_EXTPANID;
@ -314,7 +314,7 @@ void ZigbeeZCLSend_Raw(uint16_t shortaddr, uint16_t groupaddr, uint16_t clusterI
SBuffer buf(32+len);
buf.add8(Z_SREQ | Z_AF); // 24
buf.add8(AF_DATA_REQUEST_EXT); // 02
if (0x0000 == shortaddr) { // if no shortaddr we assume group address
if (BAD_SHORTADDR == shortaddr) { // if no shortaddr we assume group address
buf.add8(Z_Addr_Group); // 01
buf.add64(groupaddr); // group address, only 2 LSB, upper 6 MSB are discarded
buf.add8(0xFF); // dest endpoint is not used for group addresses
@ -372,7 +372,7 @@ void zigbeeZCLSendStr(uint16_t shortaddr, uint16_t groupaddr, uint8_t endpoint,
}
}
if ((0 == endpoint) && (shortaddr)) {
if ((0 == endpoint) && (BAD_SHORTADDR != shortaddr)) {
// endpoint is not specified, let's try to find it from shortAddr, unless it's a group address
endpoint = zigbee_devices.findFirstEndpoint(shortaddr);
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint);
@ -380,7 +380,7 @@ void zigbeeZCLSendStr(uint16_t shortaddr, uint16_t groupaddr, uint8_t endpoint,
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: shortaddr 0x%04X, groupaddr 0x%04X, cluster 0x%04X, endpoint 0x%02X, cmd 0x%02X, data %s"),
shortaddr, groupaddr, cluster, endpoint, cmd, param);
if ((0 == endpoint) && (shortaddr)) { // endpoint null is ok for group address
if ((0 == endpoint) && (BAD_SHORTADDR != shortaddr)) { // endpoint null is ok for group address
AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbSend: unspecified endpoint"));
return;
}
@ -415,7 +415,7 @@ void CmndZbSend(void) {
// params
static char delim[] = ", "; // delimiters for parameters
uint16_t device = 0x0000; // 0x0000 is local, so considered invalid
uint16_t device = BAD_SHORTADDR; // 0x0000 is local, so considered invalid
uint16_t groupaddr = 0x0000; // group address
uint8_t endpoint = 0x00; // 0x00 is invalid for the dst endpoint
uint16_t manuf = 0x0000; // Manuf Id in ZCL frame
@ -430,9 +430,9 @@ void CmndZbSend(void) {
const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device"));
if (nullptr != &val_device) {
device = zigbee_devices.parseDeviceParam(val_device.as<char*>());
if (0xFFFF == device) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
if (BAD_SHORTADDR == device) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
}
if (0x0000 == device) { // if not found, check if we have a group
if (BAD_SHORTADDR == device) { // if not found, check if we have a group
const JsonVariant &val_group = getCaseInsensitive(json, PSTR("Group"));
if (nullptr != &val_group) {
groupaddr = strToUInt(val_group);
@ -571,8 +571,8 @@ void ZbBindUnbind(bool unbind) { // false = bind, true = unbind
// params
// static char delim[] = ", "; // delimiters for parameters
uint16_t srcDevice = 0xFFFF; // 0xFFFF is broadcast, so considered invalid
uint16_t dstDevice = 0xFFFF; // 0xFFFF is broadcast, so considered invalid
uint16_t srcDevice = BAD_SHORTADDR; // BAD_SHORTADDR is broadcast, so considered invalid
uint16_t dstDevice = BAD_SHORTADDR; // BAD_SHORTADDR is broadcast, so considered invalid
uint64_t dstLongAddr = 0;
uint8_t endpoint = 0x00; // 0x00 is invalid for the src endpoint
uint8_t toendpoint = 0x00; // 0x00 is invalid for the dst endpoint
@ -585,9 +585,8 @@ void ZbBindUnbind(bool unbind) { // false = bind, true = unbind
const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device"));
if (nullptr != &val_device) {
srcDevice = zigbee_devices.parseDeviceParam(val_device.as<char*>());
if (0xFFFF == srcDevice) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
}
if ((nullptr == &val_device) || (0x0000 == srcDevice)) { ResponseCmndChar_P(PSTR("Unknown source device")); return; }
if ((nullptr == &val_device) || (BAD_SHORTADDR == srcDevice)) { ResponseCmndChar_P(PSTR("Unknown source device")); return; }
// check if IEEE address is known
uint64_t srcLongAddr = zigbee_devices.getDeviceLongAddr(srcDevice);
if (0 == srcLongAddr) { ResponseCmndChar_P(PSTR("Unknown source IEEE address")); return; }
@ -605,7 +604,7 @@ void ZbBindUnbind(bool unbind) { // false = bind, true = unbind
const JsonVariant &dst_device = getCaseInsensitive(json, PSTR("ToDevice"));
if (nullptr != &dst_device) {
dstDevice = zigbee_devices.parseDeviceParam(dst_device.as<char*>());
if (0xFFFF == dstDevice) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
if (BAD_SHORTADDR == dstDevice) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
if (0x0000 == dstDevice) {
dstLongAddr = localIEEEAddr;
} else {
@ -622,8 +621,8 @@ void ZbBindUnbind(bool unbind) { // false = bind, true = unbind
if (nullptr != &to_group) { toGroup = strToUInt(to_group); }
// make sure we don't have conflicting parameters
if (toGroup && dstLongAddr) { ResponseCmndChar_P(PSTR("Cannot have both \"ToDevice\" and \"ToGroup\"")); return; }
if (!toGroup && !dstLongAddr) { ResponseCmndChar_P(PSTR("Missing \"ToDevice\" or \"ToGroup\"")); return; }
if (&to_group && dstLongAddr) { ResponseCmndChar_P(PSTR("Cannot have both \"ToDevice\" and \"ToGroup\"")); return; }
if (!&to_group && !dstLongAddr) { ResponseCmndChar_P(PSTR("Missing \"ToDevice\" or \"ToGroup\"")); return; }
SBuffer buf(34);
buf.add8(Z_SREQ | Z_ZDO);
@ -670,8 +669,7 @@ void CmndZbUnbind(void) {
void CmndZbBindState(void) {
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data);
if (0x0000 == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
if (0xFFFF == shortaddr) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
SBuffer buf(10);
buf.add8(Z_SREQ | Z_ZDO); // 25
@ -695,8 +693,7 @@ void CmndZbProbe(void) {
void CmndZbProbeOrPing(boolean probe) {
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data);
if (0x0000 == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
if (0xFFFF == shortaddr) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
// everything is good, we can send the command
Z_SendIEEEAddrReq(shortaddr);
@ -731,8 +728,7 @@ void CmndZbName(void) {
// parse first part, <device_id>
uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); // in case of short_addr, it must be already registered
if (0x0000 == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
if (0xFFFF == shortaddr) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
if (p == nullptr) {
const char * friendlyName = zigbee_devices.getFriendlyName(shortaddr);
@ -763,8 +759,7 @@ void CmndZbModelId(void) {
// parse first part, <device_id>
uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); // in case of short_addr, it must be already registered
if (0x0000 == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
if (0xFFFF == shortaddr) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
if (p == nullptr) {
const char * modelId = zigbee_devices.getModelId(shortaddr);
@ -793,8 +788,7 @@ void CmndZbLight(void) {
// parse first part, <device_id>
uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); // in case of short_addr, it must be already registered
if (0x0000 == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
if (0xFFFF == shortaddr) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
if (p) {
int8_t bulbtype = strtol(p, nullptr, 10);
@ -817,8 +811,7 @@ void CmndZbLight(void) {
void CmndZbForget(void) {
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data);
if (0x0000 == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
if (0xFFFF == shortaddr) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
// everything is good, we can send the command
if (zigbee_devices.removeDevice(shortaddr)) {
@ -906,7 +899,7 @@ void CmndZbRead(void) {
if (!json.success()) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; }
// params
uint16_t device = 0xFFFF; // 0xFFFF is braodcast, so considered valid
uint16_t device = BAD_SHORTADDR; // BAD_SHORTADDR is broadcast, so considered invalid
uint16_t groupaddr = 0x0000; // if 0x0000 ignore group adress
uint16_t cluster = 0x0000; // default to general cluster
uint8_t endpoint = 0x00; // 0x00 is invalid for the dst endpoint
@ -917,9 +910,9 @@ void CmndZbRead(void) {
const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device"));
if (nullptr != &val_device) {
device = zigbee_devices.parseDeviceParam(val_device.as<char*>());
if (0xFFFF == device) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
if (BAD_SHORTADDR == device) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
}
if (0x0000 == device) { // if not found, check if we have a group
if (BAD_SHORTADDR == device) { // if not found, check if we have a group
const JsonVariant &val_group = getCaseInsensitive(json, PSTR("Group"));
if (nullptr != &val_group) {
groupaddr = strToUInt(val_group);
@ -960,9 +953,9 @@ void CmndZbRead(void) {
if ((0 == endpoint) && (device)) { // try to compute the endpoint
endpoint = zigbee_devices.findFirstEndpoint(device);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbRead: guessing endpoint 0x%02X"), endpoint);
}
if (0x0000 == device) {
if (BAD_SHORTADDR == device) {
endpoint = 0xFF; // endpoint not used for group addresses
}
@ -1012,9 +1005,8 @@ void CmndZbStatus(void) {
if (ZigbeeSerial) {
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data);
if (0xFFFF == shortaddr) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
if (XdrvMailbox.payload > 0) {
if (0x0000 == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
}
String dump = zigbee_devices.dump(XdrvMailbox.index, shortaddr);