mirror of https://github.com/arendst/Tasmota.git
Merge pull request #8945 from s-hadinger/zigbee_july_20
Added `SO101 1` to suffix commands with source endpoint
This commit is contained in:
commit
1182895de7
|
@ -120,7 +120,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
|
|||
uint32_t rotary_uses_rules : 1; // bit 16 (v8.3.1.6) - SetOption98 - Use rules instead of light control
|
||||
uint32_t zerocross_dimmer : 1; // bit 17 (v8.3.1.4) - SetOption99 - Enable zerocross dimmer on PWM DIMMER
|
||||
uint32_t remove_zbreceived : 1; // bit 18 (v8.3.1.7) - SetOption100 - Remove ZbReceived form JSON message
|
||||
uint32_t spare19 : 1;
|
||||
uint32_t zb_index_ep : 1; // bit 19 (v8.3.1.7) - SetOption101 - Add the source endpoint as suffix to attributes, ex `Power3` instead of `Power` if sent from endpoint 3
|
||||
uint32_t spare20 : 1;
|
||||
uint32_t spare21 : 1;
|
||||
uint32_t spare22 : 1;
|
||||
|
|
|
@ -141,6 +141,7 @@ public:
|
|||
// Add an endpoint to a device
|
||||
void addEndpoint(uint16_t shortaddr, uint8_t endpoint);
|
||||
void clearEndpoints(uint16_t shortaddr);
|
||||
uint32_t countEndpoints(uint16_t shortaddr) const; // return the number of known endpoints (0 if unknown)
|
||||
|
||||
void setManufId(uint16_t shortaddr, const char * str);
|
||||
void setModelId(uint16_t shortaddr, const char * str);
|
||||
|
@ -533,6 +534,23 @@ void Z_Devices::addEndpoint(uint16_t shortaddr, uint8_t endpoint) {
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Count the number of known endpoints
|
||||
//
|
||||
uint32_t Z_Devices::countEndpoints(uint16_t shortaddr) const {
|
||||
uint32_t count_ep = 0;
|
||||
int32_t found = findShortAddr(shortaddr);
|
||||
if (found < 0) return 0; // avoid creating an entry if the device was never seen
|
||||
const Z_Device &device = devicesAt(found);
|
||||
|
||||
for (uint32_t i = 0; i < endpoints_max; i++) {
|
||||
if (0 != device.endpoints[i]) {
|
||||
count_ep++;
|
||||
}
|
||||
}
|
||||
return count_ep;
|
||||
}
|
||||
|
||||
// Find the first endpoint of the device
|
||||
uint8_t Z_Devices::findFirstEndpoint(uint16_t shortaddr) const {
|
||||
// When in router of end-device mode, the coordinator was not probed, in this case always talk to endpoint 1
|
||||
|
|
|
@ -1157,7 +1157,7 @@ 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, _payload);
|
||||
convertClusterSpecific(json, _cluster_id, _cmd_id, _frame_control.b.direction, _srcaddr, _srcendpoint, _payload);
|
||||
sendHueUpdate(_srcaddr, _groupaddr, _cluster_id, _cmd_id, _frame_control.b.direction);
|
||||
}
|
||||
|
||||
|
@ -1423,6 +1423,8 @@ int32_t Z_ApplyConverter(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObje
|
|||
}
|
||||
|
||||
void ZCLFrame::postProcessAttributes(uint16_t shortaddr, JsonObject& json) {
|
||||
// source endpoint
|
||||
uint8_t src_ep = _srcendpoint;
|
||||
// iterate on json elements
|
||||
for (auto kv : json) {
|
||||
String key_string = kv.key;
|
||||
|
@ -1490,6 +1492,11 @@ void ZCLFrame::postProcessAttributes(uint16_t shortaddr, JsonObject& json) {
|
|||
((conv_attribute == attribute) || (conv_attribute == 0xFFFF)) ) {
|
||||
String new_name_str = (const __FlashStringHelper*) converter->name;
|
||||
if (suffix > 1) { new_name_str += suffix; } // append suffix number
|
||||
// else if (Settings.flag4.zb_index_ep) {
|
||||
// if (zigbee_devices.countEndpoints(shortaddr) > 0) {
|
||||
// new_name_str += _srcendpoint;
|
||||
// }
|
||||
// }
|
||||
// apply the transformation
|
||||
int32_t drop = Z_ApplyConverter(this, shortaddr, json, key, value, new_name_str, conv_cluster, conv_attribute, conv_multiplier, conv_cb);
|
||||
if (drop) {
|
||||
|
|
|
@ -341,7 +341,7 @@ void sendHueUpdate(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uin
|
|||
|
||||
|
||||
// Parse a cluster specific command, and try to convert into human readable
|
||||
void convertClusterSpecific(JsonObject& json, uint16_t cluster, uint8_t cmd, bool direction, const SBuffer &payload) {
|
||||
void convertClusterSpecific(JsonObject& json, uint16_t cluster, uint8_t cmd, bool direction, uint16_t shortaddr, uint8_t srcendpoint, const SBuffer &payload) {
|
||||
size_t hex_char_len = payload.len()*2+2;
|
||||
char *hex_char = (char*) malloc(hex_char_len);
|
||||
if (!hex_char) { return; }
|
||||
|
@ -414,11 +414,11 @@ void convertClusterSpecific(JsonObject& json, uint16_t cluster, uint8_t cmd, boo
|
|||
|
||||
if (command_name) {
|
||||
// Now try to transform into a human readable format
|
||||
String command_name2 = String(command_name);
|
||||
// if (direction & 0x80) then specific transform
|
||||
if (conv_direction & 0x80) {
|
||||
// TODO need to create a specific command
|
||||
// IAS
|
||||
String command_name2 = String(command_name);
|
||||
if ((cluster == 0x0500) && (cmd == 0x00)) {
|
||||
// "ZoneStatusChange"
|
||||
json[command_name] = xyz.x;
|
||||
|
@ -465,11 +465,21 @@ void convertClusterSpecific(JsonObject& json, uint16_t cluster, uint8_t cmd, boo
|
|||
String scene_payload = json[attrid_str];
|
||||
json[F("ScenePayload")] = scene_payload.substring(8); // remove first 8 characters
|
||||
}
|
||||
} else {
|
||||
} else { // general case
|
||||
bool extended_command = false; // do we send command with endpoint suffix
|
||||
// if SO101 and multiple endpoints, append endpoint number
|
||||
if (Settings.flag4.zb_index_ep) {
|
||||
if (zigbee_devices.countEndpoints(shortaddr) > 0) {
|
||||
command_name2 += srcendpoint;
|
||||
extended_command = true;
|
||||
}
|
||||
}
|
||||
if (0 == xyz.x_type) {
|
||||
json[command_name] = true; // no parameter
|
||||
if (extended_command) { json[command_name2] = true; }
|
||||
} else if (0 == xyz.y_type) {
|
||||
json[command_name] = xyz.x; // 1 parameter
|
||||
if (extended_command) { json[command_name2] = xyz.x; }
|
||||
} else {
|
||||
// multiple answers, create an array
|
||||
JsonArray &arr = json.createNestedArray(command_name);
|
||||
|
@ -478,6 +488,14 @@ void convertClusterSpecific(JsonObject& json, uint16_t cluster, uint8_t cmd, boo
|
|||
if (xyz.z_type) {
|
||||
arr.add(xyz.z);
|
||||
}
|
||||
if (extended_command) {
|
||||
JsonArray &arr = json.createNestedArray(command_name2);
|
||||
arr.add(xyz.x);
|
||||
arr.add(xyz.y);
|
||||
if (xyz.z_type) {
|
||||
arr.add(xyz.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -966,23 +966,44 @@ void EZ_SendZDO(uint16_t shortaddr, uint16_t cmd, const unsigned char *payload,
|
|||
SBuffer buf(payload_len + 22);
|
||||
uint8_t seq = zigbee_devices.getNextSeqNumber(0x0000);
|
||||
|
||||
buf.add16(EZSP_sendUnicast);
|
||||
if (shortaddr < 0xFFFC) {
|
||||
// send unicast
|
||||
buf.add16(EZSP_sendUnicast);
|
||||
|
||||
buf.add8(EMBER_OUTGOING_DIRECT); // 00
|
||||
buf.add16(shortaddr); // dest addr
|
||||
// ApsFrame
|
||||
buf.add16(0x0000); // ZOD profile
|
||||
buf.add16(cmd); // ZDO cmd in cluster
|
||||
buf.add8(0); // srcEp
|
||||
buf.add8(0); // dstEp
|
||||
buf.add16(EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY | EMBER_APS_OPTION_RETRY); // APS frame
|
||||
buf.add16(0x0000); // groupId
|
||||
buf.add8(seq);
|
||||
// end of ApsFrame
|
||||
buf.add8(0x01); // tag TODO
|
||||
buf.add8(payload_len + 1); // insert seq number
|
||||
buf.add8(seq);
|
||||
buf.addBuffer(payload, payload_len);
|
||||
buf.add8(EMBER_OUTGOING_DIRECT); // 00
|
||||
buf.add16(shortaddr); // dest addr
|
||||
// ApsFrame
|
||||
buf.add16(0x0000); // ZOD profile
|
||||
buf.add16(cmd); // ZDO cmd in cluster
|
||||
buf.add8(0); // srcEp
|
||||
buf.add8(0); // dstEp
|
||||
buf.add16(EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY | EMBER_APS_OPTION_RETRY); // APS frame
|
||||
buf.add16(0x0000); // groupId
|
||||
buf.add8(seq);
|
||||
// end of ApsFrame
|
||||
buf.add8(0x01); // tag TODO
|
||||
buf.add8(payload_len + 1); // insert seq number
|
||||
buf.add8(seq);
|
||||
buf.addBuffer(payload, payload_len);
|
||||
} else {
|
||||
// send broadcast
|
||||
buf.add16(EZSP_sendBroadcast);
|
||||
buf.add16(shortaddr); // dest addr
|
||||
// ApsFrame
|
||||
buf.add16(0x0000); // ZOD profile
|
||||
buf.add16(cmd); // ZDO cmd in cluster
|
||||
buf.add8(0); // srcEp
|
||||
buf.add8(0); // dstEp
|
||||
buf.add16(0x00); // APS frame
|
||||
buf.add16(0x0000); // groupId
|
||||
buf.add8(seq);
|
||||
// end of ApsFrame
|
||||
buf.add8(0x1E); // radius
|
||||
buf.add8(0x01); // tag TODO
|
||||
buf.add8(payload_len + 1); // insert seq number
|
||||
buf.add8(seq);
|
||||
buf.addBuffer(payload, payload_len);
|
||||
}
|
||||
|
||||
ZigbeeEZSPSendCmd(buf.buf(), buf.len(), true);
|
||||
}
|
||||
|
|
|
@ -992,12 +992,14 @@ void CmndZbPermitJoin(void) {
|
|||
|
||||
if (payload <= 0) {
|
||||
duration = 0;
|
||||
} else if (99 == payload) {
|
||||
duration = 0xFF; // unlimited time
|
||||
}
|
||||
|
||||
// ZNP Version
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
if (99 == payload) {
|
||||
duration = 0xFF; // unlimited time
|
||||
}
|
||||
|
||||
uint16_t dstAddr = 0xFFFC; // default addr
|
||||
|
||||
SBuffer buf(34);
|
||||
|
@ -1014,10 +1016,20 @@ 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);
|
||||
ZigbeeEZSPSendCmd(buf.getBuffer(), buf.len(), true);
|
||||
|
||||
// send ZDO_Mgmt_Permit_Joining_req to all routers
|
||||
buf.setLen(0);
|
||||
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()); TODO fix NAK/ACK first
|
||||
#endif // USE_ZIGBEE_EZSP
|
||||
|
||||
ResponseCmndDone();
|
||||
|
|
Loading…
Reference in New Issue