mirror of https://github.com/arendst/Tasmota.git
Merge pull request #15642 from s-hadinger/zigbee_merge_zcl
Zigbee merge ZCLMessage and ZCLFrame
This commit is contained in:
commit
1903f09b97
|
@ -30,43 +30,6 @@
|
|||
|
||||
// contains some definitions for functions used before their declarations
|
||||
|
||||
//
|
||||
// structure containing all needed information to send a ZCL packet
|
||||
//
|
||||
class ZCLMessage {
|
||||
|
||||
public:
|
||||
ZCLMessage(void); // allocate 16 bytes vy default
|
||||
ZCLMessage(size_t size);
|
||||
|
||||
inline bool validShortaddr(void) const { return BAD_SHORTADDR != shortaddr; }
|
||||
inline bool validGroupaddr(void) const { return 0 != groupaddr; }
|
||||
inline bool validCluster(void) const { return 0xFFFF != cluster; }
|
||||
inline bool validEndpoint(void) const { return 0x00 != endpoint; }
|
||||
inline bool validCmd(void) const { return 0xFF != cmd; }
|
||||
|
||||
inline void setTransac(uint8_t _transac) { transac = _transac; transacSet = true; }
|
||||
|
||||
uint16_t shortaddr = BAD_SHORTADDR; // BAD_SHORTADDR is broadcast, so considered invalid
|
||||
uint16_t groupaddr = 0x0000; // group address valid only if device == BAD_SHORTADDR
|
||||
uint16_t cluster = 0xFFFF; // no default
|
||||
uint8_t endpoint = 0x00; // 0x00 is invalid for the dst endpoint
|
||||
uint8_t cmd = 0xFF; // 0xFF is invalid command number
|
||||
uint16_t manuf = 0x0000; // default manuf id
|
||||
bool clusterSpecific = false;
|
||||
bool needResponse = true;
|
||||
bool direct = false; // true if direct, false if discover router
|
||||
bool transacSet = false; // is transac already set
|
||||
uint8_t transac = 0; // ZCL transaction number
|
||||
SBuffer buf;
|
||||
// const uint8_t *msg = nullptr;
|
||||
// size_t len = 0;
|
||||
};
|
||||
|
||||
// define constructor seperately to avoid inlining and reduce Flash size
|
||||
ZCLMessage::ZCLMessage(void) : buf(12) {};
|
||||
ZCLMessage::ZCLMessage(size_t size) : buf(size) {};
|
||||
|
||||
typedef int32_t (*ZB_Func)(uint8_t value);
|
||||
typedef int32_t (*ZB_RecvMsgFunc)(int32_t res, const SBuffer &buf);
|
||||
|
||||
|
@ -150,8 +113,8 @@ public:
|
|||
struct ZigbeeStatus zigbee;
|
||||
SBuffer *zigbee_buffer = nullptr;
|
||||
|
||||
void zigbeeZCLSendCmd(ZCLMessage &msg);
|
||||
void ZigbeeZCLSend_Raw(const ZCLMessage &zcl);
|
||||
void zigbeeZCLSendCmd(ZCLFrame &msg);
|
||||
void ZigbeeZCLSend_Raw(const ZCLFrame &zcl);
|
||||
bool ZbAppendWriteBuf(SBuffer & buf, const Z_attribute & attr, bool prepend_status_ok = false);
|
||||
|
||||
// parse Hex formatted attribute names like '0301/0001"
|
||||
|
|
|
@ -975,7 +975,7 @@ public:
|
|||
void clean(void); // avoid writing to flash the last changes
|
||||
|
||||
// Find device by name, can be short_addr, long_addr, number_in_array or name
|
||||
Z_Device & parseDeviceFromName(const char * param, uint16_t * parsed_shortaddr = nullptr);
|
||||
Z_Device & parseDeviceFromName(const char * param, uint16_t * parsed_shortaddr = nullptr, int32_t mailbox_payload = 0);
|
||||
|
||||
bool isTuyaProtocol(uint16_t shortaddr, uint8_t ep = 0) const;
|
||||
|
||||
|
@ -983,7 +983,7 @@ private:
|
|||
LList<Z_Device> _devices; // list of devices
|
||||
LList<Z_Deferred> _deferred; // list of deferred calls
|
||||
uint32_t _saveTimer = 0;
|
||||
uint8_t _seqNumber = 0; // global seqNumber if device is unknown
|
||||
uint8_t _seqnumber = 0; // global seqNumber if device is unknown
|
||||
|
||||
//int32_t findShortAddrIdx(uint16_t shortaddr) const;
|
||||
// Create a new entry in the devices list - must be called if it is sure it does not already exist
|
||||
|
@ -991,6 +991,13 @@ private:
|
|||
void freeDeviceEntry(Z_Device *device);
|
||||
};
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Berry support
|
||||
\*********************************************************************************************/
|
||||
#ifdef USE_BERRY
|
||||
extern "C" void callBerryZigbeeDispatcher(const char* type, ZCLFrame* zcl_received);
|
||||
#endif // USE_BERRY
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Singleton variable
|
||||
\*********************************************************************************************/
|
||||
|
|
|
@ -345,8 +345,8 @@ uint8_t Z_Devices::getNextSeqNumber(uint16_t shortaddr) {
|
|||
device.seqNumber += 1;
|
||||
return device.seqNumber;
|
||||
} else {
|
||||
_seqNumber += 1;
|
||||
return _seqNumber;
|
||||
_seqnumber += 1;
|
||||
return _seqnumber;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -622,7 +622,7 @@ void Z_Devices::clean(void) {
|
|||
// - a friendly name, between quotes, example: "Room_Temp"
|
||||
//
|
||||
// In case the device is not found, the parsed 0x.... short address is passed to *parsed_shortaddr
|
||||
Z_Device & Z_Devices::parseDeviceFromName(const char * param, uint16_t * parsed_shortaddr) {
|
||||
Z_Device & Z_Devices::parseDeviceFromName(const char * param, uint16_t * parsed_shortaddr, int32_t mailbox_payload) {
|
||||
if (nullptr == param) { return device_unk; }
|
||||
size_t param_len = strlen(param);
|
||||
char dataBuf[param_len + 1];
|
||||
|
@ -632,8 +632,8 @@ Z_Device & Z_Devices::parseDeviceFromName(const char * param, uint16_t * parsed_
|
|||
|
||||
if ((dataBuf[0] >= '0') && (dataBuf[0] <= '9') && (strlen(dataBuf) < 4)) {
|
||||
// simple number 0..99
|
||||
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 99)) {
|
||||
return isKnownIndexDevice(XdrvMailbox.payload - 1);
|
||||
if ((mailbox_payload > 0) && (mailbox_payload <= 99)) {
|
||||
return isKnownIndexDevice(mailbox_payload - 1);
|
||||
} else {
|
||||
return device_unk;
|
||||
}
|
||||
|
|
|
@ -722,18 +722,25 @@ const __FlashStringHelper* zigbeeFindAttributeById(uint16_t cluster, uint16_t at
|
|||
class ZCLFrame {
|
||||
public:
|
||||
|
||||
// constructor used when creating a message from scratch to send it later
|
||||
ZCLFrame(void); // allocate 16 bytes by default
|
||||
ZCLFrame(size_t size);
|
||||
|
||||
// constructore used when receiving a Zigbee frame and populating the class
|
||||
ZCLFrame(uint8_t frame_control, uint16_t manuf_code, uint8_t transact_seq, uint8_t cmd_id,
|
||||
const char *buf, size_t buf_len, uint16_t clusterid, uint16_t groupaddr,
|
||||
uint16_t srcaddr, uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast,
|
||||
uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber):
|
||||
_manuf_code(manuf_code), _transact_seq(transact_seq), _cmd_id(cmd_id),
|
||||
_payload(buf_len ? buf_len : 250), // allocate the data frame from source or preallocate big enough
|
||||
_cluster_id(clusterid), _groupaddr(groupaddr),
|
||||
_srcaddr(srcaddr), _srcendpoint(srcendpoint), _dstendpoint(dstendpoint), _wasbroadcast(wasbroadcast),
|
||||
manuf(manuf_code), transactseq(transact_seq), cmd(cmd_id),
|
||||
payload(buf_len ? buf_len : 250), // allocate the data frame from source or preallocate big enough
|
||||
cluster(clusterid), groupaddr(groupaddr),
|
||||
shortaddr(srcaddr), _srcendpoint(srcendpoint), dstendpoint(dstendpoint), _wasbroadcast(wasbroadcast),
|
||||
_linkquality(linkquality), _securityuse(securityuse), _seqnumber(seqnumber)
|
||||
{
|
||||
_frame_control.d8 = frame_control;
|
||||
_payload.addBuffer(buf, buf_len);
|
||||
clusterSpecific = (_frame_control.b.frame_type != 0);
|
||||
needResponse = !_frame_control.b.disable_def_resp;
|
||||
payload.addBuffer(buf, buf_len);
|
||||
};
|
||||
|
||||
|
||||
|
@ -746,13 +753,13 @@ public:
|
|||
"\"frametype\":%d,\"direction\":%d,\"disableresp\":%d,"
|
||||
"\"manuf\":\"0x%04X\",\"transact\":%d,"
|
||||
"\"cmdid\":\"0x%02X\",\"payload\":\"%_B\"}}"),
|
||||
_groupaddr, _cluster_id, _srcaddr,
|
||||
_srcendpoint, _dstendpoint, _wasbroadcast,
|
||||
groupaddr, cluster, shortaddr,
|
||||
_srcendpoint, dstendpoint, _wasbroadcast,
|
||||
_linkquality, _securityuse, _seqnumber,
|
||||
_frame_control,
|
||||
_frame_control.b.frame_type, _frame_control.b.direction, _frame_control.b.disable_def_resp,
|
||||
_manuf_code, _transact_seq, _cmd_id,
|
||||
&_payload);
|
||||
manuf, transactseq, cmd,
|
||||
&payload);
|
||||
if (Settings->flag3.tuya_serial_mqtt_publish) {
|
||||
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_SENSOR));
|
||||
} else {
|
||||
|
@ -788,6 +795,7 @@ public:
|
|||
return _frame_control.b.frame_type & 1;
|
||||
}
|
||||
|
||||
// parsers for received messages
|
||||
void parseReportAttributes(Z_attribute_list& attr_list);
|
||||
void generateSyntheticAttributes(Z_attribute_list& attr_list);
|
||||
void removeInvalidAttributes(Z_attribute_list& attr_list);
|
||||
|
@ -813,47 +821,59 @@ public:
|
|||
void autoResponder(const uint16_t *attr_list_ids, size_t attr_len);
|
||||
|
||||
inline void setGroupId(uint16_t groupid) {
|
||||
_groupaddr = groupid;
|
||||
groupaddr = groupid;
|
||||
}
|
||||
|
||||
inline void setClusterId(uint16_t clusterid) {
|
||||
_cluster_id = clusterid;
|
||||
cluster = clusterid;
|
||||
}
|
||||
|
||||
inline uint16_t getSrcAddr(void) const { return _srcaddr; }
|
||||
inline uint16_t getGroupAddr(void) const { return _groupaddr; }
|
||||
inline uint16_t getClusterId(void) const { return _cluster_id; }
|
||||
inline uint16_t getSrcAddr(void) const { return shortaddr; }
|
||||
inline uint16_t getGroupAddr(void) const { return groupaddr; }
|
||||
inline uint16_t getClusterId(void) const { return cluster; }
|
||||
inline uint8_t getLinkQuality(void) const { return _linkquality; }
|
||||
inline uint8_t getCmdId(void) const { return _cmd_id; }
|
||||
inline uint8_t getCmdId(void) const { return cmd; }
|
||||
inline uint16_t getSrcEndpoint(void) const { return _srcendpoint; }
|
||||
const SBuffer &getPayload(void) const { return payload; }
|
||||
uint16_t getManufCode(void) const { return manuf; }
|
||||
|
||||
const SBuffer &getPayload(void) const {
|
||||
return _payload;
|
||||
}
|
||||
inline void setTransac(uint8_t _transac) { transactseq = _transac; transacSet = true; }
|
||||
|
||||
uint16_t getManufCode(void) const {
|
||||
return _manuf_code;
|
||||
}
|
||||
inline bool validShortaddr(void) const { return BAD_SHORTADDR != shortaddr; }
|
||||
inline bool validCluster(void) const { return 0xFFFF != cluster; }
|
||||
inline bool validEndpoint(void) const { return 0x00 != dstendpoint; }
|
||||
inline bool validCmd(void) const { return 0xFF != cmd; }
|
||||
|
||||
|
||||
private:
|
||||
ZCLHeaderFrameControl_t _frame_control = { .d8 = 0 };
|
||||
uint16_t _manuf_code = 0; // optional
|
||||
uint8_t _transact_seq = 0; // transaction sequence number
|
||||
uint8_t _cmd_id = 0;
|
||||
SBuffer _payload;
|
||||
uint16_t _cluster_id = 0;
|
||||
uint16_t _groupaddr = 0;
|
||||
public:
|
||||
uint16_t manuf = 0; // optional
|
||||
uint8_t transactseq = 0; // transaction sequence number
|
||||
uint8_t cmd = 0;
|
||||
SBuffer payload;
|
||||
uint16_t cluster = 0;
|
||||
uint16_t groupaddr = 0;
|
||||
// information from decoded ZCL frame
|
||||
uint16_t _srcaddr;
|
||||
uint8_t _srcendpoint;
|
||||
uint8_t _dstendpoint;
|
||||
uint8_t _wasbroadcast;
|
||||
uint8_t _linkquality;
|
||||
uint8_t _securityuse;
|
||||
uint8_t _seqnumber;
|
||||
uint16_t shortaddr = BAD_SHORTADDR; // BAD_SHORTADDR is broadcast, so considered invalid
|
||||
uint8_t dstendpoint = 0x00; // 0x00 is invalid for the dst endpoint
|
||||
// attributes used in send-only mode
|
||||
bool clusterSpecific = false;
|
||||
bool needResponse = true;
|
||||
bool direct = false; // true if direct, false if discover router
|
||||
bool transacSet = false; // is transac already set
|
||||
|
||||
// below private attributes are not used when sending a message
|
||||
private:
|
||||
uint8_t _srcendpoint = 0x00; // 0x00 is invalid for the src endpoint
|
||||
ZCLHeaderFrameControl_t _frame_control = { .d8 = 0 };
|
||||
bool _wasbroadcast = false;
|
||||
uint8_t _linkquality = 0x00;
|
||||
uint8_t _securityuse = 0; // not used by Z2T, logging only
|
||||
uint8_t _seqnumber = 0; // not used by Z2T, logging only
|
||||
};
|
||||
|
||||
// define constructor seperately to avoid inlining and reduce Flash size
|
||||
ZCLFrame::ZCLFrame(void) : payload(12) {};
|
||||
ZCLFrame::ZCLFrame(size_t size) : payload(size) {};
|
||||
|
||||
// Zigbee ZCL converters
|
||||
|
||||
// from https://github.com/Koenkk/zigbee-shepherd-converters/blob/638d29f0cace6343052b9a4e7fd60980fa785479/converters/fromZigbee.js#L55
|
||||
|
@ -1197,45 +1217,45 @@ uint32_t parseSingleAttribute(Z_attribute & attr, const SBuffer &buf,
|
|||
// First pass, parse all attributes in their native format
|
||||
void ZCLFrame::parseReportAttributes(Z_attribute_list& attr_list) {
|
||||
uint32_t i = 0;
|
||||
uint32_t len = _payload.len();
|
||||
uint32_t len = payload.len();
|
||||
|
||||
if (ZCL_WRITE_ATTRIBUTES == getCmdId()) {
|
||||
attr_list.addAttribute(PSTR("Command"), true).setStr(PSTR("Write"));
|
||||
}
|
||||
|
||||
while (len >= i + 3) {
|
||||
uint16_t attrid = _payload.get16(i);
|
||||
uint16_t attrid = payload.get16(i);
|
||||
i += 2;
|
||||
|
||||
// exception for Xiaomi lumi.weather - specific field to be treated as octet and not char
|
||||
if ((0x0000 == _cluster_id) && (0xFF01 == attrid)) {
|
||||
if (0x42 == _payload.get8(i)) {
|
||||
_payload.set8(i, 0x41); // change type from 0x42 to 0x41
|
||||
if ((0x0000 == cluster) && (0xFF01 == attrid)) {
|
||||
if (0x42 == payload.get8(i)) {
|
||||
payload.set8(i, 0x41); // change type from 0x42 to 0x41
|
||||
}
|
||||
}
|
||||
|
||||
// TODO look for suffix
|
||||
Z_attribute & attr = attr_list.addAttribute(_cluster_id, attrid);
|
||||
Z_attribute & attr = attr_list.addAttribute(cluster, attrid);
|
||||
|
||||
i += parseSingleAttribute(attr, _payload, i);
|
||||
i += parseSingleAttribute(attr, payload, i);
|
||||
}
|
||||
|
||||
// Issue Philips outdoor motion sensor SML002, see https://github.com/Koenkk/zigbee2mqtt/issues/897
|
||||
// The sensor expects the coordinator to send a Default Response to acknowledge the attribute reporting
|
||||
if (0 == _frame_control.b.disable_def_resp) {
|
||||
// the device expects a default response
|
||||
ZCLMessage zcl(2); // message is 2 bytes
|
||||
zcl.shortaddr = _srcaddr;
|
||||
zcl.cluster = _cluster_id;
|
||||
zcl.endpoint = _srcendpoint;
|
||||
ZCLFrame zcl(2); // message is 2 bytes
|
||||
zcl.shortaddr = shortaddr;
|
||||
zcl.cluster = cluster;
|
||||
zcl.dstendpoint = _srcendpoint;
|
||||
zcl.cmd = ZCL_DEFAULT_RESPONSE;
|
||||
zcl.manuf = _manuf_code;
|
||||
zcl.manuf = manuf;
|
||||
zcl.clusterSpecific = false; /* not cluster specific */
|
||||
zcl.needResponse = false; /* noresponse */
|
||||
zcl.direct = true; /* direct no retry */
|
||||
zcl.setTransac(_transact_seq);
|
||||
zcl.buf.add8(_cmd_id);
|
||||
zcl.buf.add8(0); // Status = OK
|
||||
zcl.setTransac(transactseq);
|
||||
zcl.payload.add8(cmd);
|
||||
zcl.payload.add8(0); // Status = OK
|
||||
zigbeeZCLSendCmd(zcl);
|
||||
}
|
||||
}
|
||||
|
@ -1295,8 +1315,8 @@ void ZCLFrame::removeInvalidAttributes(Z_attribute_list& attr_list) {
|
|||
// Note: both function are now split to compute on extracted attributes
|
||||
//
|
||||
void ZCLFrame::computeSyntheticAttributes(Z_attribute_list& attr_list) {
|
||||
const Z_Device & device = zigbee_devices.findShortAddr(_srcaddr);
|
||||
const char * model_c = zigbee_devices.getModelId(_srcaddr); // null if unknown
|
||||
const Z_Device & device = zigbee_devices.findShortAddr(shortaddr);
|
||||
const char * model_c = zigbee_devices.getModelId(shortaddr); // null if unknown
|
||||
String modelId((char*) model_c);
|
||||
// scan through attributes and apply specific converters
|
||||
for (auto &attr : attr_list) {
|
||||
|
@ -1324,7 +1344,7 @@ void ZCLFrame::computeSyntheticAttributes(Z_attribute_list& attr_list) {
|
|||
case 0x02010008: // Pi Heating Demand - solve Eutotronic bug
|
||||
case 0x02014008: // Eurotronic Host Flags decoding
|
||||
{
|
||||
const char * manufacturer_c = zigbee_devices.getManufacturerId(_srcaddr); // null if unknown
|
||||
const char * manufacturer_c = zigbee_devices.getManufacturerId(shortaddr); // null if unknown
|
||||
String manufacturerId((char*) manufacturer_c);
|
||||
if (manufacturerId.equals(F("Eurotronic"))) {
|
||||
if (ccccaaaa == 0x02010008) {
|
||||
|
@ -1382,7 +1402,7 @@ void ZCLFrame::computeSyntheticAttributes(Z_attribute_list& attr_list) {
|
|||
}
|
||||
break;
|
||||
case 0x05000002: // ZoneStatus
|
||||
const Z_Data_Alarm & alarm = (const Z_Data_Alarm&) zigbee_devices.getShortAddr(_srcaddr).data.find(Z_Data_Type::Z_Alarm, _srcendpoint);
|
||||
const Z_Data_Alarm & alarm = (const Z_Data_Alarm&) zigbee_devices.getShortAddr(shortaddr).data.find(Z_Data_Type::Z_Alarm, _srcendpoint);
|
||||
if (&alarm != nullptr) {
|
||||
alarm.convertZoneStatus(attr_list, attr.getUInt());
|
||||
}
|
||||
|
@ -1405,15 +1425,15 @@ void ZCLFrame::generateCallBacks(Z_attribute_list& attr_list) {
|
|||
uint32_t occupancy = attr.getUInt();
|
||||
if (occupancy) {
|
||||
uint32_t pir_timer = OCCUPANCY_TIMEOUT;
|
||||
const Z_Data_PIR & pir_found = (const Z_Data_PIR&) zigbee_devices.getShortAddr(_srcaddr).data.find(Z_Data_Type::Z_PIR, _srcendpoint);
|
||||
const Z_Data_PIR & pir_found = (const Z_Data_PIR&) zigbee_devices.getShortAddr(shortaddr).data.find(Z_Data_Type::Z_PIR, _srcendpoint);
|
||||
if (&pir_found != nullptr) {
|
||||
pir_timer = pir_found.getTimeoutSeconds() * 1000;
|
||||
}
|
||||
if (pir_timer > 0) {
|
||||
zigbee_devices.setTimer(_srcaddr, 0 /* groupaddr */, pir_timer, _cluster_id, _srcendpoint, Z_CAT_VIRTUAL_OCCUPANCY, 0, &Z_OccupancyCallback);
|
||||
zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, pir_timer, cluster, _srcendpoint, Z_CAT_VIRTUAL_OCCUPANCY, 0, &Z_OccupancyCallback);
|
||||
}
|
||||
} else {
|
||||
zigbee_devices.resetTimersForDevice(_srcaddr, 0 /* groupaddr */, Z_CAT_VIRTUAL_OCCUPANCY);
|
||||
zigbee_devices.resetTimersForDevice(shortaddr, 0 /* groupaddr */, Z_CAT_VIRTUAL_OCCUPANCY);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1460,16 +1480,16 @@ void sendHueUpdate(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uin
|
|||
// ZCL_READ_ATTRIBUTES
|
||||
void ZCLFrame::parseReadAttributes(Z_attribute_list& attr_list) {
|
||||
uint32_t i = 0;
|
||||
uint32_t len = _payload.len();
|
||||
uint32_t len = payload.len();
|
||||
|
||||
uint16_t read_attr_ids[len/2];
|
||||
|
||||
attr_list.addAttributePMEM(PSTR(D_CMND_ZIGBEE_CLUSTER)).setUInt(_cluster_id);
|
||||
attr_list.addAttributePMEM(PSTR(D_CMND_ZIGBEE_CLUSTER)).setUInt(cluster);
|
||||
|
||||
JsonGeneratorArray attr_numbers;
|
||||
Z_attribute_list attr_names;
|
||||
while (len >= 2 + i) {
|
||||
uint16_t attrid = _payload.get16(i);
|
||||
uint16_t attrid = payload.get16(i);
|
||||
attr_numbers.add(attrid);
|
||||
read_attr_ids[i/2] = attrid;
|
||||
|
||||
|
@ -1479,7 +1499,7 @@ void ZCLFrame::parseReadAttributes(Z_attribute_list& attr_list) {
|
|||
uint16_t conv_cluster = CxToCluster(pgm_read_byte(&converter->cluster_short));
|
||||
uint16_t conv_attribute = pgm_read_word(&converter->attribute);
|
||||
|
||||
if ((conv_cluster == _cluster_id) && (conv_attribute == attrid)) {
|
||||
if ((conv_cluster == cluster) && (conv_attribute == attrid)) {
|
||||
attr_names.addAttribute(Z_strings + pgm_read_word(&converter->name_offset), true).setBool(true);
|
||||
break;
|
||||
}
|
||||
|
@ -1490,29 +1510,29 @@ void ZCLFrame::parseReadAttributes(Z_attribute_list& attr_list) {
|
|||
attr_list.addAttributePMEM(PSTR("ReadNames")).setStrRaw(attr_names.toString(true).c_str());
|
||||
|
||||
// call auto-responder only if src address if different from ourselves and it was a broadcast
|
||||
if (_srcaddr != localShortAddr || !_wasbroadcast) {
|
||||
if (shortaddr != localShortAddr || !_wasbroadcast) {
|
||||
autoResponder(read_attr_ids, len/2);
|
||||
}
|
||||
}
|
||||
|
||||
// ZCL_CONFIGURE_REPORTING_RESPONSE
|
||||
void ZCLFrame::parseConfigAttributes(Z_attribute_list& attr_list) {
|
||||
uint32_t len = _payload.len();
|
||||
uint32_t len = payload.len();
|
||||
|
||||
Z_attribute_list attr_config_list;
|
||||
for (uint32_t i=0; len >= i+4; i+=4) {
|
||||
uint8_t status = _payload.get8(i);
|
||||
uint16_t attr_id = _payload.get8(i+2);
|
||||
uint8_t status = payload.get8(i);
|
||||
uint16_t attr_id = payload.get8(i+2);
|
||||
|
||||
Z_attribute_list attr_config_response;
|
||||
attr_config_response.addAttributePMEM(PSTR("Status")).setUInt(status);
|
||||
attr_config_response.addAttributePMEM(PSTR("StatusMsg")).setStr(getZigbeeStatusMessage(status).c_str());
|
||||
|
||||
const __FlashStringHelper* attr_name = zigbeeFindAttributeById(_cluster_id, attr_id, nullptr, nullptr);
|
||||
const __FlashStringHelper* attr_name = zigbeeFindAttributeById(cluster, attr_id, nullptr, nullptr);
|
||||
if (attr_name) {
|
||||
attr_config_list.addAttribute(attr_name).setStrRaw(attr_config_response.toString(true).c_str());
|
||||
} else {
|
||||
attr_config_list.addAttribute(_cluster_id, attr_id).setStrRaw(attr_config_response.toString(true).c_str());
|
||||
attr_config_list.addAttribute(cluster, attr_id).setStrRaw(attr_config_response.toString(true).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1522,21 +1542,21 @@ void ZCLFrame::parseConfigAttributes(Z_attribute_list& attr_list) {
|
|||
|
||||
// ZCL_WRITE_ATTRIBUTES_RESPONSE
|
||||
void ZCLFrame::parseWriteAttributesResponse(Z_attribute_list& attr_list) {
|
||||
parseResponse_inner(ZCL_WRITE_ATTRIBUTES_RESPONSE, false, _payload.get8(0));
|
||||
parseResponse_inner(ZCL_WRITE_ATTRIBUTES_RESPONSE, false, payload.get8(0));
|
||||
}
|
||||
|
||||
// ZCL_READ_REPORTING_CONFIGURATION_RESPONSE
|
||||
void ZCLFrame::parseReadConfigAttributes(Z_attribute_list& attr_list) {
|
||||
uint32_t i = 0;
|
||||
uint32_t len = _payload.len();
|
||||
uint32_t len = payload.len();
|
||||
|
||||
Z_attribute &attr_root = attr_list.addAttributePMEM(PSTR("ReadConfig"));
|
||||
Z_attribute_list attr_1;
|
||||
|
||||
while (len >= i + 4) {
|
||||
uint8_t status = _payload.get8(i);
|
||||
uint8_t direction = _payload.get8(i+1);
|
||||
uint16_t attrid = _payload.get16(i+2);
|
||||
uint8_t status = payload.get8(i);
|
||||
uint8_t direction = payload.get8(i+1);
|
||||
uint16_t attrid = payload.get16(i+2);
|
||||
|
||||
Z_attribute_list attr_2;
|
||||
if (direction) {
|
||||
|
@ -1550,7 +1570,7 @@ void ZCLFrame::parseReadConfigAttributes(Z_attribute_list& attr_list) {
|
|||
uint16_t conv_cluster = CxToCluster(pgm_read_byte(&converter->cluster_short));
|
||||
uint16_t conv_attribute = pgm_read_word(&converter->attribute);
|
||||
|
||||
if ((conv_cluster == _cluster_id) && (conv_attribute == attrid)) {
|
||||
if ((conv_cluster == cluster) && (conv_attribute == attrid)) {
|
||||
const char * attr_name = Z_strings + pgm_read_word(&converter->name_offset);
|
||||
attr_2.addAttribute(attr_name, true).setBool(true);
|
||||
multiplier = CmToMultiplier(pgm_read_byte(&converter->multiplier_idx));
|
||||
|
@ -1565,22 +1585,22 @@ void ZCLFrame::parseReadConfigAttributes(Z_attribute_list& attr_list) {
|
|||
// no error, decode data
|
||||
if (direction) {
|
||||
// only Timeout period is present
|
||||
uint16_t attr_timeout = _payload.get16(i);
|
||||
uint16_t attr_timeout = payload.get16(i);
|
||||
i += 2;
|
||||
attr_2.addAttributePMEM(PSTR("TimeoutPeriod")).setUInt((0xFFFF == attr_timeout) ? -1 : attr_timeout);
|
||||
} else {
|
||||
// direction == 0, we have a data type
|
||||
uint8_t attr_type = _payload.get8(i);
|
||||
uint8_t attr_type = payload.get8(i);
|
||||
bool attr_discrete = Z_isDiscreteDataType(attr_type);
|
||||
uint16_t attr_min_interval = _payload.get16(i+1);
|
||||
uint16_t attr_max_interval = _payload.get16(i+3);
|
||||
uint16_t attr_min_interval = payload.get16(i+1);
|
||||
uint16_t attr_max_interval = payload.get16(i+3);
|
||||
i += 5;
|
||||
attr_2.addAttributePMEM(PSTR("MinInterval")).setUInt((0xFFFF == attr_min_interval) ? -1 : attr_min_interval);
|
||||
attr_2.addAttributePMEM(PSTR("MaxInterval")).setUInt((0xFFFF == attr_max_interval) ? -1 : attr_max_interval);
|
||||
if (!attr_discrete) {
|
||||
// decode Reportable Change
|
||||
Z_attribute &attr_change = attr_2.addAttributePMEM(PSTR("ReportableChange"));
|
||||
i += parseSingleAttribute(attr_change, _payload, i, attr_type);
|
||||
i += parseSingleAttribute(attr_change, payload, i, attr_type);
|
||||
if ((1 != multiplier) && (0 != multiplier)) {
|
||||
float fval = attr_change.getFloat();
|
||||
if (multiplier > 0) { fval = fval * multiplier; }
|
||||
|
@ -1590,7 +1610,7 @@ void ZCLFrame::parseReadConfigAttributes(Z_attribute_list& attr_list) {
|
|||
}
|
||||
}
|
||||
}
|
||||
attr_1.addAttribute(_cluster_id, attrid).setStrRaw(attr_2.toString(true).c_str());
|
||||
attr_1.addAttribute(cluster, attrid).setStrRaw(attr_2.toString(true).c_str());
|
||||
}
|
||||
attr_root.setStrRaw(attr_1.toString(true).c_str());
|
||||
}
|
||||
|
@ -1598,16 +1618,16 @@ void ZCLFrame::parseReadConfigAttributes(Z_attribute_list& attr_list) {
|
|||
// ZCL_READ_ATTRIBUTES_RESPONSE
|
||||
void ZCLFrame::parseReadAttributesResponse(Z_attribute_list& attr_list) {
|
||||
uint32_t i = 0;
|
||||
uint32_t len = _payload.len();
|
||||
uint32_t len = payload.len();
|
||||
|
||||
while (len >= i + 4) {
|
||||
uint16_t attrid = _payload.get16(i);
|
||||
uint16_t attrid = payload.get16(i);
|
||||
i += 2;
|
||||
uint8_t status = _payload.get8(i++);
|
||||
uint8_t status = payload.get8(i++);
|
||||
|
||||
if (0 == status) {
|
||||
Z_attribute & attr = attr_list.addAttribute(_cluster_id, attrid);
|
||||
i += parseSingleAttribute(attr, _payload, i);
|
||||
Z_attribute & attr = attr_list.addAttribute(cluster, attrid);
|
||||
i += parseSingleAttribute(attr, payload, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1618,15 +1638,15 @@ void ZCLFrame::parseResponse_inner(uint8_t cmd, bool cluster_specific, uint8_t s
|
|||
|
||||
// "Device"
|
||||
char s[12];
|
||||
snprintf_P(s, sizeof(s), PSTR("0x%04X"), _srcaddr);
|
||||
snprintf_P(s, sizeof(s), PSTR("0x%04X"), shortaddr);
|
||||
attr_list.addAttributePMEM(PSTR(D_JSON_ZIGBEE_DEVICE)).setStr(s);
|
||||
// "Name"
|
||||
const char * friendlyName = zigbee_devices.getFriendlyName(_srcaddr);
|
||||
const char * friendlyName = zigbee_devices.getFriendlyName(shortaddr);
|
||||
if (friendlyName) {
|
||||
attr_list.addAttributePMEM(PSTR(D_JSON_ZIGBEE_NAME)).setStr(friendlyName);
|
||||
}
|
||||
// "Command"
|
||||
snprintf_P(s, sizeof(s), PSTR("%04X%c%02X"), _cluster_id, cluster_specific ? '!' : '_', cmd);
|
||||
snprintf_P(s, sizeof(s), PSTR("%04X%c%02X"), cluster, cluster_specific ? '!' : '_', cmd);
|
||||
attr_list.addAttributePMEM(PSTR(D_JSON_ZIGBEE_CMD)).setStr(s);
|
||||
// "Status"
|
||||
attr_list.addAttributePMEM(PSTR(D_JSON_ZIGBEE_STATUS)).setUInt(status);
|
||||
|
@ -1635,8 +1655,8 @@ void ZCLFrame::parseResponse_inner(uint8_t cmd, bool cluster_specific, uint8_t s
|
|||
// Add Endpoint
|
||||
attr_list.addAttributePMEM(PSTR(D_CMND_ZIGBEE_ENDPOINT)).setUInt(_srcendpoint);
|
||||
// Add Group if non-zero
|
||||
if (_groupaddr) { // TODO what about group zero
|
||||
attr_list.group_id = _groupaddr;
|
||||
if (groupaddr) { // TODO what about group zero
|
||||
attr_list.group_id = groupaddr;
|
||||
}
|
||||
// Add linkquality
|
||||
attr_list.lqi = _linkquality;
|
||||
|
@ -1647,9 +1667,9 @@ void ZCLFrame::parseResponse_inner(uint8_t cmd, bool cluster_specific, uint8_t s
|
|||
|
||||
// ZCL_DEFAULT_RESPONSE
|
||||
void ZCLFrame::parseResponse(void) {
|
||||
if (_payload.len() < 2) { return; } // wrong format
|
||||
uint8_t cmd = _payload.get8(0);
|
||||
uint8_t status = _payload.get8(1);
|
||||
if (payload.len() < 2) { return; } // wrong format
|
||||
uint8_t cmd = payload.get8(0);
|
||||
uint8_t status = payload.get8(1);
|
||||
|
||||
parseResponse_inner(cmd, true, status);
|
||||
}
|
||||
|
@ -1665,22 +1685,22 @@ void Z_ResetDebounce(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, u
|
|||
// Parse non-normalized attributes
|
||||
void ZCLFrame::parseClusterSpecificCommand(Z_attribute_list& attr_list) {
|
||||
// Check if debounce is active and if the packet is a duplicate
|
||||
Z_Device & device = zigbee_devices.getShortAddr(_srcaddr);
|
||||
if ((device.debounce_endpoint != 0) && (device.debounce_endpoint == _srcendpoint) && (device.debounce_transact == _transact_seq)) {
|
||||
Z_Device & device = zigbee_devices.getShortAddr(shortaddr);
|
||||
if ((device.debounce_endpoint != 0) && (device.debounce_endpoint == _srcendpoint) && (device.debounce_transact == transactseq)) {
|
||||
// this is a duplicate, drop the packet
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "Discarding duplicate command from 0x%04X, endpoint %d"), _srcaddr, _srcendpoint);
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "Discarding duplicate command from 0x%04X, endpoint %d"), shortaddr, _srcendpoint);
|
||||
} else {
|
||||
// reset the duplicate marker, parse the packet normally, and set a timer to reset the marker later (which will discard any existing timer for the same device/endpoint)
|
||||
device.debounce_endpoint = _srcendpoint;
|
||||
device.debounce_transact = _transact_seq;
|
||||
zigbee_devices.setTimer(_srcaddr, 0 /* groupaddr */, USE_ZIGBEE_DEBOUNCE_COMMANDS, 0 /*clusterid*/, _srcendpoint, Z_CAT_DEBOUNCE_CMD, 0, &Z_ResetDebounce);
|
||||
device.debounce_transact = transactseq;
|
||||
zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, USE_ZIGBEE_DEBOUNCE_COMMANDS, 0 /*clusterid*/, _srcendpoint, Z_CAT_DEBOUNCE_CMD, 0, &Z_ResetDebounce);
|
||||
|
||||
convertClusterSpecific(attr_list, _cluster_id, _cmd_id, _frame_control.b.direction, _srcaddr, _srcendpoint, _payload);
|
||||
convertClusterSpecific(attr_list, cluster, cmd, _frame_control.b.direction, shortaddr, _srcendpoint, payload);
|
||||
if (!Settings->flag5.zb_disable_autoquery) {
|
||||
// read attributes unless disabled
|
||||
if (!_frame_control.b.direction) { // only handle server->client (i.e. device->coordinator)
|
||||
if (_wasbroadcast) { // only update for broadcast messages since we don't see unicast from device to device and we wouldn't know the target
|
||||
sendHueUpdate(BAD_SHORTADDR, _groupaddr, _cluster_id);
|
||||
sendHueUpdate(BAD_SHORTADDR, groupaddr, cluster);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1688,18 +1708,18 @@ void ZCLFrame::parseClusterSpecificCommand(Z_attribute_list& attr_list) {
|
|||
// Send Default Response to acknowledge the attribute reporting
|
||||
if (0 == _frame_control.b.disable_def_resp) {
|
||||
// the device expects a default response
|
||||
ZCLMessage zcl(2); // message is 4 bytes
|
||||
zcl.shortaddr = _srcaddr;
|
||||
zcl.cluster = _cluster_id;
|
||||
zcl.endpoint = _srcendpoint;
|
||||
ZCLFrame zcl(2); // message is 4 bytes
|
||||
zcl.shortaddr = shortaddr;
|
||||
zcl.cluster = cluster;
|
||||
zcl.dstendpoint = _srcendpoint;
|
||||
zcl.cmd = ZCL_DEFAULT_RESPONSE;
|
||||
zcl.manuf = _manuf_code;
|
||||
zcl.manuf = manuf;
|
||||
zcl.clusterSpecific = false; /* not cluster specific */
|
||||
zcl.needResponse = false; /* noresponse */
|
||||
zcl.direct = true; /* direct no retry */
|
||||
zcl.setTransac(_transact_seq);
|
||||
zcl.buf.add8(_cmd_id);
|
||||
zcl.buf.add8(0x00); // Status = OK
|
||||
zcl.setTransac(transactseq);
|
||||
zcl.payload.add8(cmd);
|
||||
zcl.payload.add8(0x00); // Status = OK
|
||||
zigbeeZCLSendCmd(zcl);
|
||||
}
|
||||
}
|
||||
|
@ -1707,7 +1727,7 @@ void ZCLFrame::parseClusterSpecificCommand(Z_attribute_list& attr_list) {
|
|||
// ======================================================================
|
||||
// Convert AnalogValue according to the device type
|
||||
void ZCLFrame::syntheticAnalogValue(Z_attribute_list &attr_list, class Z_attribute &attr) {
|
||||
const char * modelId_c = zigbee_devices.getModelId(_srcaddr); // null if unknown
|
||||
const char * modelId_c = zigbee_devices.getModelId(shortaddr); // null if unknown
|
||||
String modelId((char*) modelId_c);
|
||||
|
||||
if (modelId.startsWith(F("lumi.sensor_cube"))) {
|
||||
|
@ -1731,7 +1751,7 @@ void ZCLFrame::syntheticAqaraSensor(Z_attribute_list &attr_list, class Z_attribu
|
|||
uint32_t i = 0;
|
||||
uint32_t len = buf2.len();
|
||||
|
||||
const char * modelId_c = zigbee_devices.getModelId(_srcaddr); // null if unknown
|
||||
const char * modelId_c = zigbee_devices.getModelId(shortaddr); // null if unknown
|
||||
String modelId((char*) modelId_c);
|
||||
|
||||
while (len >= 2 + i) {
|
||||
|
@ -1830,7 +1850,7 @@ void ZCLFrame::syntheticAqaraSensor2(class Z_attribute_list &attr_list, class Z_
|
|||
|
||||
// Aqara Cube and Button
|
||||
void ZCLFrame::syntheticAqaraCubeOrButton(class Z_attribute_list &attr_list, class Z_attribute &attr) {
|
||||
const char * modelId_c = zigbee_devices.findShortAddr(_srcaddr).modelId; // null if unknown
|
||||
const char * modelId_c = zigbee_devices.findShortAddr(shortaddr).modelId; // null if unknown
|
||||
String modelId((char*) modelId_c);
|
||||
|
||||
if (modelId.startsWith(F("lumi.sensor_cube"))) { // only for Aqara cube
|
||||
|
|
|
@ -152,14 +152,14 @@ void ZigbeeHueGroups(String * lights) {
|
|||
}
|
||||
|
||||
void ZigbeeSendHue(uint16_t shortaddr, uint16_t cluster, uint8_t cmd, const SBuffer & s) {
|
||||
ZCLMessage zcl(s.len());
|
||||
ZCLFrame zcl(s.len());
|
||||
zcl.shortaddr = shortaddr;
|
||||
zcl.cluster = cluster;
|
||||
zcl.cmd = cmd;
|
||||
zcl.clusterSpecific = true;
|
||||
zcl.needResponse = true;
|
||||
zcl.direct = false; // discover route
|
||||
zcl.buf.replace(s);
|
||||
zcl.payload.replace(s);
|
||||
zigbeeZCLSendCmd(zcl);
|
||||
}
|
||||
|
|
@ -183,16 +183,16 @@ void Z_ReadAttrCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster
|
|||
shortaddr = BAD_SHORTADDR; // if group address, don't send to device
|
||||
}
|
||||
|
||||
ZCLMessage zcl(attrs_len); // message is `attrs_len` bytes
|
||||
ZCLFrame zcl(attrs_len); // message is `attrs_len` bytes
|
||||
zcl.shortaddr = shortaddr;
|
||||
zcl.groupaddr = groupaddr;
|
||||
zcl.cluster = cluster;
|
||||
zcl.endpoint = endpoint;
|
||||
zcl.dstendpoint = endpoint;
|
||||
zcl.cmd = ZCL_READ_ATTRIBUTES;
|
||||
zcl.clusterSpecific = false;
|
||||
zcl.needResponse = true;
|
||||
zcl.direct = false; // discover route
|
||||
zcl.buf.addBuffer(attrs, attrs_len);
|
||||
zcl.payload.addBuffer(attrs, attrs_len);
|
||||
zigbeeZCLSendCmd(zcl);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1380,15 +1380,15 @@ void Z_SendSimpleDescReq(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluste
|
|||
// Iterate among
|
||||
//
|
||||
void Z_SendDeviceInfoRequest(uint16_t shortaddr) {
|
||||
ZCLMessage zcl(4); // message is 4 bytes
|
||||
ZCLFrame zcl(4); // message is 4 bytes
|
||||
zcl.shortaddr = shortaddr;
|
||||
zcl.cluster = 0;
|
||||
zcl.cmd = ZCL_READ_ATTRIBUTES;
|
||||
zcl.clusterSpecific = false;
|
||||
zcl.needResponse = true;
|
||||
zcl.direct = false; // discover route
|
||||
zcl.buf.add16(0x0005);
|
||||
zcl.buf.add16(0x0004);
|
||||
zcl.payload.add16(0x0005);
|
||||
zcl.payload.add16(0x0004);
|
||||
zigbeeZCLSendCmd(zcl);
|
||||
}
|
||||
|
||||
|
@ -1396,15 +1396,15 @@ void Z_SendDeviceInfoRequest(uint16_t shortaddr) {
|
|||
// Send single attribute read request in Timer
|
||||
//
|
||||
void Z_SendSingleAttributeRead(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) {
|
||||
ZCLMessage zcl(2); // message is 2 bytes
|
||||
ZCLFrame zcl(2); // message is 2 bytes
|
||||
zcl.shortaddr = shortaddr;
|
||||
zcl.cluster = cluster;
|
||||
zcl.endpoint = endpoint;
|
||||
zcl.dstendpoint = endpoint;
|
||||
zcl.cmd = ZCL_READ_ATTRIBUTES;
|
||||
zcl.clusterSpecific = false;
|
||||
zcl.needResponse = true;
|
||||
zcl.direct = false; // discover route
|
||||
zcl.buf.add16(value); // 04000500
|
||||
zcl.payload.add16(value); // 04000500
|
||||
zigbeeZCLSendCmd(zcl);
|
||||
}
|
||||
|
||||
|
@ -1413,17 +1413,17 @@ void Z_SendSingleAttributeRead(uint16_t shortaddr, uint16_t groupaddr, uint16_t
|
|||
//
|
||||
void Z_WriteCIEAddress(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) {
|
||||
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Sending CIE Address for Cluster %d in Endpoint %d of Device 0x%04X"), cluster, endpoint, shortaddr);
|
||||
ZCLMessage zcl(12); // message is 12 bytes
|
||||
ZCLFrame zcl(12); // message is 12 bytes
|
||||
zcl.shortaddr = shortaddr;
|
||||
zcl.cluster = 0x0500;
|
||||
zcl.endpoint = endpoint;
|
||||
zcl.dstendpoint = endpoint;
|
||||
zcl.cmd = ZCL_WRITE_ATTRIBUTES;
|
||||
zcl.clusterSpecific = false;
|
||||
zcl.needResponse = true;
|
||||
zcl.direct = false; // discover route
|
||||
zcl.buf.add16(0x0010); // attribute 0x0010
|
||||
zcl.buf.add8(ZEUI64);
|
||||
zcl.buf.add64(localIEEEAddr);
|
||||
zcl.payload.add16(0x0010); // attribute 0x0010
|
||||
zcl.payload.add8(ZEUI64);
|
||||
zcl.payload.add64(localIEEEAddr);
|
||||
zigbeeZCLSendCmd(zcl);
|
||||
}
|
||||
|
||||
|
@ -1433,16 +1433,16 @@ void Z_WriteCIEAddress(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster,
|
|||
//
|
||||
void Z_SendCIEZoneEnrollResponse(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) {
|
||||
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Sending Enroll Zone %d for Cluster %d in Endpoint %d of Device 0x%04X"), Z_B0(value), cluster, endpoint, shortaddr);
|
||||
ZCLMessage zcl(2); // message is 2 bytes
|
||||
ZCLFrame zcl(2); // message is 2 bytes
|
||||
zcl.shortaddr = shortaddr;
|
||||
zcl.cluster = 0x0500;
|
||||
zcl.endpoint = endpoint;
|
||||
zcl.dstendpoint = endpoint;
|
||||
zcl.cmd = 0x00; // Zone Enroll Response
|
||||
zcl.clusterSpecific = true;
|
||||
zcl.needResponse = true;
|
||||
zcl.direct = false; // discover route
|
||||
zcl.buf.add8(0x00); // success
|
||||
zcl.buf.add8(Z_B0(value)); // ZoneID
|
||||
zcl.payload.add8(0x00); // success
|
||||
zcl.payload.add8(Z_B0(value)); // ZoneID
|
||||
zigbeeZCLSendCmd(zcl);
|
||||
}
|
||||
|
||||
|
@ -1579,15 +1579,15 @@ void Z_AutoConfigReportingForCluster(uint16_t shortaddr, uint16_t groupaddr, uin
|
|||
|
||||
if (buf.len() > 0) {
|
||||
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "auto-bind `%s`"), ResponseData());
|
||||
ZCLMessage zcl(buf.len()); // message is 4 bytes
|
||||
ZCLFrame zcl(buf.len()); // message is 4 bytes
|
||||
zcl.shortaddr = shortaddr;
|
||||
zcl.cluster = cluster;
|
||||
zcl.endpoint = endpoint;
|
||||
zcl.dstendpoint = endpoint;
|
||||
zcl.cmd = ZCL_CONFIGURE_REPORTING;
|
||||
zcl.clusterSpecific = false; /* not cluster specific */
|
||||
zcl.needResponse = false; /* noresponse */
|
||||
zcl.direct = false; /* discover route */
|
||||
zcl.buf.addBuffer(buf);
|
||||
zcl.payload.addBuffer(buf);
|
||||
zigbeeZCLSendCmd(zcl);
|
||||
}
|
||||
}
|
||||
|
@ -1639,6 +1639,11 @@ void Z_IncomingMessage(class ZCLFrame &zcl_received) {
|
|||
// log the packet details
|
||||
zcl_received.log();
|
||||
|
||||
#ifdef USE_BERRY
|
||||
// Berry pre-process messages
|
||||
// callBerryZigbeeDispatcher("pre", &zcl_received);
|
||||
#endif // USE_BERRY
|
||||
|
||||
// create the device entry if it does not exist and if it's not the local device
|
||||
Z_Device & device = (srcaddr != localShortAddr) ? zigbee_devices.getShortAddr(srcaddr) :
|
||||
device_unk;
|
||||
|
@ -2097,9 +2102,9 @@ void ZCLFrame::autoResponder(const uint16_t *attr_list_ids, size_t attr_len) {
|
|||
|
||||
for (uint32_t i=0; i<attr_len; i++) {
|
||||
uint16_t attr_id = attr_list_ids[i];
|
||||
uint32_t ccccaaaa = (_cluster_id << 16) | attr_id;
|
||||
uint32_t ccccaaaa = (cluster << 16) | attr_id;
|
||||
Z_attribute attr;
|
||||
attr.setKeyId(_cluster_id, attr_id);
|
||||
attr.setKeyId(cluster, attr_id);
|
||||
|
||||
switch (ccccaaaa) {
|
||||
case 0x00000004: attr.setStr(PSTR(USE_ZIGBEE_MANUFACTURER)); break; // Manufacturer
|
||||
|
@ -2149,8 +2154,8 @@ void ZCLFrame::autoResponder(const uint16_t *attr_list_ids, size_t attr_len) {
|
|||
break;
|
||||
}
|
||||
if (!attr.isNone()) {
|
||||
Z_parseAttributeKey(attr, _cluster_id);
|
||||
attr_list.addAttribute(_cluster_id, attr_id) = attr;
|
||||
Z_parseAttributeKey(attr, cluster);
|
||||
attr_list.addAttribute(cluster, attr_id) = attr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2170,21 +2175,21 @@ void ZCLFrame::autoResponder(const uint16_t *attr_list_ids, size_t attr_len) {
|
|||
",\"Endpoint\":%d"
|
||||
",\"Response\":%s}"
|
||||
),
|
||||
_srcaddr, _cluster_id, _srcendpoint,
|
||||
shortaddr, cluster, _srcendpoint,
|
||||
attr_list.toString().c_str());
|
||||
|
||||
// send
|
||||
// all good, send the packet
|
||||
ZCLMessage zcl(buf.len()); // message is 4 bytes
|
||||
zcl.shortaddr = _srcaddr;
|
||||
zcl.cluster = _cluster_id;
|
||||
zcl.endpoint = _srcendpoint;
|
||||
ZCLFrame zcl(buf.len()); // message is 4 bytes
|
||||
zcl.shortaddr = shortaddr;
|
||||
zcl.cluster = cluster;
|
||||
zcl.dstendpoint = _srcendpoint;
|
||||
zcl.cmd = ZCL_READ_ATTRIBUTES_RESPONSE;
|
||||
zcl.clusterSpecific = false; /* not cluster specific */
|
||||
zcl.needResponse = false; /* noresponse */
|
||||
zcl.direct = true; /* direct response */
|
||||
zcl.setTransac(_transact_seq);
|
||||
zcl.buf.addBuffer(buf);
|
||||
zcl.setTransac(transactseq);
|
||||
zcl.payload.addBuffer(buf);
|
||||
zigbeeZCLSendCmd(zcl);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -753,12 +753,12 @@ void CmndZbEZSPSend(void)
|
|||
// - msg: pointer to byte array, payload of ZCL message (len is following), ignored if nullptr
|
||||
// - len: length of the 'msg' payload
|
||||
// - needResponse: boolean, true = we ask the target to respond, false = the target should not respond
|
||||
// - transac: 8-bits, transation id of message (should be incremented at each message), used both for Zigbee message number and ZCL message number
|
||||
// - transactseq: 8-bits, transation id of message (should be incremented at each message), used both for Zigbee message number and ZCL message number
|
||||
// Returns: None
|
||||
//
|
||||
|
||||
void ZigbeeZCLSend_Raw(const ZCLMessage &zcl) {
|
||||
SBuffer buf(32+zcl.buf.len());
|
||||
void ZigbeeZCLSend_Raw(const ZCLFrame &zcl) {
|
||||
SBuffer buf(32+zcl.payload.len());
|
||||
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
buf.add8(Z_SREQ | Z_AF); // 24
|
||||
|
@ -770,23 +770,23 @@ void ZigbeeZCLSend_Raw(const ZCLMessage &zcl) {
|
|||
} else {
|
||||
buf.add8(Z_Addr_ShortAddress); // 02
|
||||
buf.add64(zcl.shortaddr); // dest address, only 2 LSB, upper 6 MSB are discarded
|
||||
buf.add8(zcl.endpoint); // dest endpoint
|
||||
buf.add8(zcl.dstendpoint); // dest endpoint
|
||||
}
|
||||
buf.add16(0x0000); // dest Pan ID, 0x0000 = intra-pan
|
||||
buf.add8(0x01); // source endpoint
|
||||
buf.add16(zcl.cluster);
|
||||
buf.add8(zcl.transac); // transac
|
||||
buf.add8(zcl.transactseq); // transactseq
|
||||
buf.add8(0x30); // 30 options
|
||||
buf.add8(0x1E); // 1E radius
|
||||
|
||||
buf.add16(3 + zcl.buf.len() + (zcl.manuf ? 2 : 0));
|
||||
buf.add16(3 + zcl.payload.len() + (zcl.manuf ? 2 : 0));
|
||||
buf.add8((zcl.needResponse ? 0x00 : 0x10) | (zcl.clusterSpecific ? 0x01 : 0x00) | (zcl.manuf ? 0x04 : 0x00)); // Frame Control Field
|
||||
if (zcl.manuf) {
|
||||
buf.add16(zcl.manuf); // add Manuf Id if not null
|
||||
}
|
||||
buf.add8(zcl.transac); // Transaction Sequence Number
|
||||
buf.add8(zcl.transactseq); // Transaction Sequence Number
|
||||
buf.add8(zcl.cmd);
|
||||
buf.addBuffer(zcl.buf);
|
||||
buf.addBuffer(zcl.payload);
|
||||
|
||||
ZigbeeZNPSend(buf.getBuffer(), buf.len());
|
||||
#endif // USE_ZIGBEE_ZNP
|
||||
|
@ -801,25 +801,25 @@ void ZigbeeZCLSend_Raw(const ZCLMessage &zcl) {
|
|||
buf.add16(Z_PROF_HA); // Home Automation profile
|
||||
buf.add16(zcl.cluster); // cluster
|
||||
buf.add8(0x01); // srcEp
|
||||
buf.add8(zcl.endpoint); // dstEp
|
||||
buf.add8(zcl.dstendpoint); // dstEp
|
||||
if (zcl.direct) {
|
||||
buf.add16(0x0000); // APS frame
|
||||
} else {
|
||||
buf.add16(EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY | EMBER_APS_OPTION_RETRY); // APS frame
|
||||
}
|
||||
buf.add16(zcl.groupaddr); // groupId
|
||||
buf.add8(zcl.transac);
|
||||
buf.add8(zcl.transactseq);
|
||||
// end of ApsFrame
|
||||
buf.add8(0x01); // tag TODO
|
||||
|
||||
buf.add8(3 + zcl.buf.len() + (zcl.manuf ? 2 : 0));
|
||||
buf.add8(3 + zcl.payload.len() + (zcl.manuf ? 2 : 0));
|
||||
buf.add8((zcl.needResponse ? 0x00 : 0x10) | (zcl.clusterSpecific ? 0x01 : 0x00) | (zcl.manuf ? 0x04 : 0x00)); // Frame Control Field
|
||||
if (zcl.manuf) {
|
||||
buf.add16(zcl.manuf); // add Manuf Id if not null
|
||||
}
|
||||
buf.add8(zcl.transac); // Transaction Sequance Number
|
||||
buf.add8(zcl.transactseq); // Transaction Sequance Number
|
||||
buf.add8(zcl.cmd);
|
||||
buf.addBuffer(zcl.buf);
|
||||
buf.addBuffer(zcl.payload);
|
||||
} else {
|
||||
// send broadcast group address, aka groupcast
|
||||
buf.add16(EZSP_sendMulticast); // 3800
|
||||
|
@ -827,27 +827,27 @@ void ZigbeeZCLSend_Raw(const ZCLMessage &zcl) {
|
|||
buf.add16(Z_PROF_HA); // Home Automation profile
|
||||
buf.add16(zcl.cluster); // cluster
|
||||
buf.add8(0x01); // srcEp
|
||||
buf.add8(zcl.endpoint); // broadcast endpoint for groupcast
|
||||
buf.add8(zcl.dstendpoint); // broadcast endpoint for groupcast
|
||||
if (zcl.direct) {
|
||||
buf.add16(0x0000); // APS frame
|
||||
} else {
|
||||
buf.add16(EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY | EMBER_APS_OPTION_RETRY); // APS frame
|
||||
}
|
||||
buf.add16(zcl.groupaddr); // groupId
|
||||
buf.add8(zcl.transac);
|
||||
buf.add8(zcl.transactseq);
|
||||
// end of ApsFrame
|
||||
buf.add8(0); // hops, 0x00 = EMBER_MAX_HOPS
|
||||
buf.add8(7); // nonMemberRadius, 7 = infinite
|
||||
buf.add8(0x01); // tag TODO
|
||||
|
||||
buf.add8(3 + zcl.buf.len() + (zcl.manuf ? 2 : 0));
|
||||
buf.add8(3 + zcl.payload.len() + (zcl.manuf ? 2 : 0));
|
||||
buf.add8((zcl.needResponse ? 0x00 : 0x10) | (zcl.clusterSpecific ? 0x01 : 0x00) | (zcl.manuf ? 0x04 : 0x00)); // Frame Control Field
|
||||
if (zcl.manuf) {
|
||||
buf.add16(zcl.manuf); // add Manuf Id if not null
|
||||
}
|
||||
buf.add8(zcl.transac); // Transaction Sequance Number
|
||||
buf.add8(zcl.transactseq); // Transaction Sequance Number
|
||||
buf.add8(zcl.cmd);
|
||||
buf.addBuffer(zcl.buf);
|
||||
buf.addBuffer(zcl.payload);
|
||||
}
|
||||
|
||||
ZigbeeEZSPSendCmd(buf.buf(), buf.len());
|
||||
|
|
|
@ -178,18 +178,18 @@ void CmndZbReset(void) {
|
|||
// - param: pointer to HEX string for payload, should not be nullptr
|
||||
// Returns: None
|
||||
//
|
||||
void zigbeeZCLSendCmd(class ZCLMessage &zcl) {
|
||||
if ((0 == zcl.endpoint) && (zcl.validShortaddr())) {
|
||||
void zigbeeZCLSendCmd(class ZCLFrame &zcl) {
|
||||
if ((0 == zcl.dstendpoint) && (zcl.validShortaddr())) {
|
||||
// endpoint is not specified, let's try to find it from shortAddr, unless it's a group address
|
||||
zcl.endpoint = zigbee_devices.findFirstEndpoint(zcl.shortaddr);
|
||||
if (0x00 == zcl.endpoint) { zcl.endpoint = 0x01; } // if we don't know the endpoint, try 0x01
|
||||
zcl.dstendpoint = zigbee_devices.findFirstEndpoint(zcl.shortaddr);
|
||||
if (0x00 == zcl.dstendpoint) { zcl.dstendpoint = 0x01; } // if we don't know the endpoint, try 0x01
|
||||
//AddLog(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint);
|
||||
}
|
||||
|
||||
// AddLog(LOG_LEVEL_DEBUG, PSTR("ZbSend: shortaddr 0x%04X, groupaddr 0x%04X, cluster 0x%04X, endpoint 0x%02X, cmd 0x%02X, data %_B"),
|
||||
// zcl.shortaddr, zcl.groupaddr, zcl.cluster, zcl.endpoint, zcl.cmd, &zcl.buf);
|
||||
// zcl.shortaddr, zcl.groupaddr, zcl.cluster, zcl.dstendpoint, zcl.cmd, &zcl.payload);
|
||||
|
||||
if ((0 == zcl.endpoint) && (zcl.validShortaddr())) { // endpoint null is ok for group address
|
||||
if ((0 == zcl.dstendpoint) && (zcl.validShortaddr())) { // endpoint null is ok for group address
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("ZbSend: unspecified endpoint"));
|
||||
return;
|
||||
}
|
||||
|
@ -197,12 +197,12 @@ void zigbeeZCLSendCmd(class ZCLMessage &zcl) {
|
|||
// everything is good, we can send the command
|
||||
|
||||
if (!zcl.transacSet) {
|
||||
zcl.transac = zigbee_devices.getNextSeqNumber(zcl.shortaddr);
|
||||
zcl.transactseq = zigbee_devices.getNextSeqNumber(zcl.shortaddr);
|
||||
zcl.transacSet = true;
|
||||
}
|
||||
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("ZigbeeZCLSend %s: 0x%04X, endpoint:%d, cluster:0x%04X, cmd:0x%02X, send:\"%_B\""),
|
||||
zcl.validShortaddr() ? "device":"group", zcl.validShortaddr() ? zcl.shortaddr : zcl.groupaddr, zcl.endpoint, zcl.cluster, zcl.cmd, &zcl.buf);
|
||||
zcl.validShortaddr() ? "device":"group", zcl.validShortaddr() ? zcl.shortaddr : zcl.groupaddr, zcl.dstendpoint, zcl.cluster, zcl.cmd, &zcl.payload);
|
||||
|
||||
ZigbeeZCLSend_Raw(zcl);
|
||||
|
||||
|
@ -210,7 +210,7 @@ void zigbeeZCLSendCmd(class ZCLMessage &zcl) {
|
|||
if (zcl.clusterSpecific) {
|
||||
if (!Settings->flag5.zb_disable_autoquery) {
|
||||
// read back attribute value unless it is disabled
|
||||
sendHueUpdate(zcl.shortaddr, zcl.groupaddr, zcl.cluster, zcl.endpoint);
|
||||
sendHueUpdate(zcl.shortaddr, zcl.groupaddr, zcl.cluster, zcl.dstendpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -321,15 +321,15 @@ bool ZbAppendWriteBuf(SBuffer & buf, const Z_attribute & attr, bool prepend_stat
|
|||
// Parse "Report", "Write", "Response" or "Config" attribute
|
||||
// Operation is one of: ZCL_REPORT_ATTRIBUTES (0x0A), ZCL_WRITE_ATTRIBUTES (0x02) or ZCL_READ_ATTRIBUTES_RESPONSE (0x01)
|
||||
//
|
||||
void ZbSendReportWrite(class JsonParserToken val_pubwrite, class ZCLMessage & zcl) {
|
||||
zcl.buf.reserve(200); // buffer to store the binary output of attibutes
|
||||
SBuffer & buf = zcl.buf; // synonym
|
||||
void ZbSendReportWrite(class JsonParserToken val_pubwrite, class ZCLFrame & zcl) {
|
||||
zcl.payload.reserve(200); // buffer to store the binary output of attibutes
|
||||
SBuffer & buf = zcl.payload; // synonym
|
||||
|
||||
if (nullptr == XdrvMailbox.command) {
|
||||
XdrvMailbox.command = (char*) ""; // prevent a crash when calling ReponseCmndChar and there was no previous command
|
||||
}
|
||||
|
||||
bool tuya_protocol = zigbee_devices.isTuyaProtocol(zcl.shortaddr, zcl.endpoint);
|
||||
bool tuya_protocol = zigbee_devices.isTuyaProtocol(zcl.shortaddr, zcl.dstendpoint);
|
||||
|
||||
// iterate on keys
|
||||
for (auto key : val_pubwrite.getObject()) {
|
||||
|
@ -449,7 +449,7 @@ void ZbSendReportWrite(class JsonParserToken val_pubwrite, class ZCLMessage & zc
|
|||
}
|
||||
|
||||
// Parse the "Send" attribute and send the command
|
||||
void ZbSendSend(class JsonParserToken val_cmd, ZCLMessage & zcl) {
|
||||
void ZbSendSend(class JsonParserToken val_cmd, ZCLFrame & zcl) {
|
||||
zcl.clusterSpecific = true;
|
||||
|
||||
static const char delim[] = ", "; // delimiters for parameters
|
||||
|
@ -525,7 +525,7 @@ void ZbSendSend(class JsonParserToken val_cmd, ZCLMessage & zcl) {
|
|||
} else {
|
||||
zcl.cmd = cmd_var; // or simply copy the cmd number
|
||||
}
|
||||
zigbeeCmdAddParams(zcl.buf, tasmota_cmd, x, y, z); // fill in parameters
|
||||
zigbeeCmdAddParams(zcl.payload, tasmota_cmd, x, y, z); // fill in parameters
|
||||
} else {
|
||||
// we have zero command, pass through until last error for missing command
|
||||
return;
|
||||
|
@ -563,7 +563,7 @@ void ZbSendSend(class JsonParserToken val_cmd, ZCLMessage & zcl) {
|
|||
// delimiter is optional
|
||||
if ('/' == *data) { data++; } // skip delimiter
|
||||
|
||||
zcl.buf.replace(SBuffer::SBufferFromHex(data, strlen(data)));
|
||||
zcl.payload.replace(SBuffer::SBufferFromHex(data, strlen(data)));
|
||||
zigbeeZCLSendCmd(zcl);
|
||||
} else {
|
||||
// we have an unsupported command type
|
||||
|
@ -574,7 +574,7 @@ void ZbSendSend(class JsonParserToken val_cmd, ZCLMessage & zcl) {
|
|||
}
|
||||
|
||||
// Parse the "Send" attribute and send the command
|
||||
void ZbSendRead(JsonParserToken val_attr, ZCLMessage & zcl) {
|
||||
void ZbSendRead(JsonParserToken val_attr, ZCLFrame & zcl) {
|
||||
// ZbSend {"Device":"0xF289","Cluster":0,"Endpoint":3,"Read":5}
|
||||
// ZbSend {"Device":"0xF289","Cluster":"0x0000","Endpoint":"0x0003","Read":"0x0005"}
|
||||
// ZbSend {"Device":"0xF289","Cluster":0,"Endpoint":3,"Read":[5,6,7,4]}
|
||||
|
@ -670,9 +670,9 @@ void ZbSendRead(JsonParserToken val_attr, ZCLMessage & zcl) {
|
|||
|
||||
if (attrs_len > 0) {
|
||||
// all good, send the packet
|
||||
zcl.buf.reserve(attrs_len);
|
||||
zcl.buf.setLen(0); // clear any previous buffer
|
||||
zcl.buf.addBuffer(attrs, attrs_len);
|
||||
zcl.payload.reserve(attrs_len);
|
||||
zcl.payload.setLen(0); // clear any previous buffer
|
||||
zcl.payload.addBuffer(attrs, attrs_len);
|
||||
zigbeeZCLSendCmd(zcl);
|
||||
ResponseCmndDone();
|
||||
} else {
|
||||
|
@ -712,7 +712,7 @@ void CmndZbSend(void) {
|
|||
if (!root) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; }
|
||||
|
||||
// params
|
||||
ZCLMessage zcl; // prepare the ZCL structure
|
||||
ZCLFrame zcl; // prepare the ZCL structure
|
||||
|
||||
// parse "Device" and "Group"
|
||||
JsonParserToken val_device = root[PSTR(D_CMND_ZIGBEE_DEVICE)];
|
||||
|
@ -733,15 +733,15 @@ void CmndZbSend(void) {
|
|||
|
||||
// read other parameters
|
||||
zcl.cluster = root.getUInt(PSTR(D_CMND_ZIGBEE_CLUSTER), zcl.cluster);
|
||||
zcl.endpoint = root.getUInt(PSTR(D_CMND_ZIGBEE_ENDPOINT), zcl.endpoint);
|
||||
zcl.dstendpoint = root.getUInt(PSTR(D_CMND_ZIGBEE_ENDPOINT), zcl.dstendpoint);
|
||||
zcl.manuf = root.getUInt(PSTR(D_CMND_ZIGBEE_MANUF), zcl.manuf);
|
||||
|
||||
// infer endpoint
|
||||
if (!zcl.validShortaddr()) {
|
||||
zcl.endpoint = 0xFF; // endpoint not used for group addresses, so use a dummy broadcast endpoint
|
||||
zcl.dstendpoint = 0xFF; // endpoint not used for group addresses, so use a dummy broadcast endpoint
|
||||
} else if (!zcl.validEndpoint()) { // if it was not already specified, try to guess it
|
||||
zcl.endpoint = zigbee_devices.findFirstEndpoint(zcl.shortaddr);
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("ZIG: guessing endpoint %d"), zcl.endpoint);
|
||||
zcl.dstendpoint = zigbee_devices.findFirstEndpoint(zcl.shortaddr);
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("ZIG: guessing endpoint %d"), zcl.dstendpoint);
|
||||
}
|
||||
if (!zcl.validEndpoint()) { // after this, if it is still zero, then it's an error
|
||||
ResponseCmndChar_P(PSTR("Missing endpoint"));
|
||||
|
@ -848,7 +848,7 @@ void ZbBindUnbind(bool unbind) { // false = bind, true = unbind
|
|||
|
||||
// Information about source device: "Device", "Endpoint", "Cluster"
|
||||
// - the source endpoint must have a known IEEE address
|
||||
const Z_Device & src_device = zigbee_devices.parseDeviceFromName(root.getStr(PSTR(D_CMND_ZIGBEE_DEVICE), nullptr));
|
||||
const Z_Device & src_device = zigbee_devices.parseDeviceFromName(root.getStr(PSTR(D_CMND_ZIGBEE_DEVICE)));
|
||||
if (!src_device.valid()) { ResponseCmndChar_P(PSTR("Unknown source device")); return; }
|
||||
// check if IEEE address is known
|
||||
uint64_t srcLongAddr = src_device.longaddr;
|
||||
|
@ -961,7 +961,7 @@ void CmndZbUnbind(void) {
|
|||
//
|
||||
void CmndZbLeave(void) {
|
||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||
uint16_t shortaddr = zigbee_devices.parseDeviceFromName(XdrvMailbox.data).shortaddr;
|
||||
uint16_t shortaddr = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, nullptr, XdrvMailbox.payload).shortaddr;
|
||||
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR(D_ZIGBEE_UNKNOWN_DEVICE)); return; }
|
||||
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
|
@ -993,7 +993,7 @@ void CmndZbLeave(void) {
|
|||
void CmndZbBindState_or_Map(bool map) {
|
||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||
uint16_t parsed_shortaddr;;
|
||||
uint16_t shortaddr = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, &parsed_shortaddr).shortaddr;
|
||||
uint16_t shortaddr = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, &parsed_shortaddr, XdrvMailbox.payload).shortaddr;
|
||||
if (BAD_SHORTADDR == shortaddr) {
|
||||
if ((map) && (parsed_shortaddr != shortaddr)) {
|
||||
shortaddr = parsed_shortaddr; // allow a non-existent address when ZbMap
|
||||
|
@ -1069,7 +1069,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.parseDeviceFromName(XdrvMailbox.data).shortaddr;
|
||||
uint16_t shortaddr = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, nullptr, XdrvMailbox.payload).shortaddr;
|
||||
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR(D_ZIGBEE_UNKNOWN_DEVICE)); return; }
|
||||
|
||||
// set a timer for Reachable - 2s default value
|
||||
|
@ -1107,7 +1107,7 @@ void CmndZbName(void) {
|
|||
strtok_r(XdrvMailbox.data, ",", &p);
|
||||
|
||||
// parse first part, <device_id>
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data); // it's the only case where we create a new device
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, nullptr, XdrvMailbox.payload); // it's the only case where we create a new device
|
||||
if (!device.valid()) { ResponseCmndChar_P(PSTR(D_ZIGBEE_UNKNOWN_DEVICE)); return; }
|
||||
|
||||
if (p == nullptr) {
|
||||
|
@ -1139,7 +1139,7 @@ void CmndZbModelId(void) {
|
|||
strtok_r(XdrvMailbox.data, ",", &p);
|
||||
|
||||
// parse first part, <device_id>
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data); // in case of short_addr, it must be already registered
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, nullptr, XdrvMailbox.payload); // in case of short_addr, it must be already registered
|
||||
if (!device.valid()) { ResponseCmndChar_P(PSTR(D_ZIGBEE_UNKNOWN_DEVICE)); return; }
|
||||
|
||||
if (p != nullptr) {
|
||||
|
@ -1166,7 +1166,7 @@ void CmndZbLight(void) {
|
|||
strtok_r(XdrvMailbox.data, ", ", &p);
|
||||
|
||||
// parse first part, <device_id>
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data); // in case of short_addr, it must be already registered
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, nullptr, XdrvMailbox.payload); // in case of short_addr, it must be already registered
|
||||
if (!device.valid()) { ResponseCmndChar_P(PSTR(D_ZIGBEE_UNKNOWN_DEVICE)); return; }
|
||||
|
||||
if (p) {
|
||||
|
@ -1210,7 +1210,7 @@ void CmndZbOccupancy(void) {
|
|||
strtok_r(XdrvMailbox.data, ", ", &p);
|
||||
|
||||
// parse first part, <device_id>
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data); // in case of short_addr, it must be already registered
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, nullptr, XdrvMailbox.payload); // in case of short_addr, it must be already registered
|
||||
if (!device.valid()) { ResponseCmndChar_P(PSTR(D_ZIGBEE_UNKNOWN_DEVICE)); return; }
|
||||
|
||||
int8_t occupancy_time = -1;
|
||||
|
@ -1237,7 +1237,7 @@ void CmndZbOccupancy(void) {
|
|||
//
|
||||
void CmndZbForget(void) {
|
||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data); // in case of short_addr, it must be already registered
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, nullptr, XdrvMailbox.payload); // in case of short_addr, it must be already registered
|
||||
if (!device.valid()) { ResponseCmndChar_P(PSTR(D_ZIGBEE_UNKNOWN_DEVICE)); return; }
|
||||
|
||||
// everything is good, we can send the command
|
||||
|
@ -1267,7 +1267,7 @@ void CmndZbInfo(void) {
|
|||
CmndZbInfo_inner(device);
|
||||
}
|
||||
} else { // try JSON
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data); // in case of short_addr, it must be already registered
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, nullptr, XdrvMailbox.payload); // in case of short_addr, it must be already registered
|
||||
if (!device.valid()) { ResponseCmndChar_P(PSTR(D_ZIGBEE_UNKNOWN_DEVICE)); return; }
|
||||
|
||||
// everything is good, we can send the command
|
||||
|
@ -1337,7 +1337,7 @@ void CmndZbenroll(void) {
|
|||
|
||||
if ((XdrvMailbox.data_len) && (ArgC() > 1)) { // Process parameter entry
|
||||
char argument[XdrvMailbox.data_len];
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(ArgV(argument, 1));
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(ArgV(argument, 1), nullptr, XdrvMailbox.payload);
|
||||
int enrollEndpoint = atoi(ArgV(argument, 2));
|
||||
|
||||
if (!device.valid()) { ResponseCmndChar_P(PSTR(D_ZIGBEE_UNKNOWN_DEVICE)); return; }
|
||||
|
@ -1355,7 +1355,7 @@ void CmndZbcie(void) {
|
|||
|
||||
if ((XdrvMailbox.data_len) && (ArgC() > 1)) { // Process parameter entry
|
||||
char argument[XdrvMailbox.data_len];
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(ArgV(argument, 1));
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(ArgV(argument, 1), nullptr, XdrvMailbox.payload);
|
||||
int enrollEndpoint = atoi(ArgV(argument, 2));
|
||||
|
||||
if (!device.valid()) { ResponseCmndChar_P(PSTR(D_ZIGBEE_UNKNOWN_DEVICE)); return; }
|
||||
|
@ -1576,7 +1576,7 @@ void CmndZbStatus(void) {
|
|||
if (0 == XdrvMailbox.index) {
|
||||
dump = zigbee_devices.dumpCoordinator();
|
||||
} else {
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data);
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, nullptr, XdrvMailbox.payload);
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
if (!device.valid()) { ResponseCmndChar_P(PSTR(D_ZIGBEE_UNKNOWN_DEVICE)); return; }
|
||||
dump = zigbee_devices.dumpDevice(XdrvMailbox.index, device);
|
||||
|
@ -1608,7 +1608,7 @@ void CmndZbData(void) {
|
|||
strtok_r(XdrvMailbox.data, ",", &p);
|
||||
|
||||
// parse first part, <device_id>
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data); // in case of short_addr, it must be already registered
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, nullptr, XdrvMailbox.payload); // in case of short_addr, it must be already registered
|
||||
if (!device.valid()) { ResponseCmndChar_P(PSTR(D_ZIGBEE_UNKNOWN_DEVICE)); return; }
|
||||
|
||||
if (p) {
|
||||
|
|
Loading…
Reference in New Issue