mirror of https://github.com/arendst/Tasmota.git
Merge pull request #8035 from s-hadinger/zigbee_bindstate
Add Zigbee commands ``ZbBindState`` and ``manuf``attribute
This commit is contained in:
commit
b982ea8d08
|
@ -3,6 +3,7 @@
|
|||
### 8.2.0.3 20200329
|
||||
|
||||
- Add support for longer template names
|
||||
- Add Zigbee commands ``ZbBindState`` and ``manuf``attribute
|
||||
|
||||
### 8.2.0.2 20200328
|
||||
|
||||
|
|
|
@ -507,6 +507,8 @@
|
|||
#define D_JSON_ZIGBEE_BIND "ZbBind"
|
||||
#define D_CMND_ZIGBEE_UNBIND "Unbind"
|
||||
#define D_JSON_ZIGBEE_UNBIND "ZbUnbind"
|
||||
#define D_CMND_ZIGBEE_BIND_STATE "BindState"
|
||||
#define D_JSON_ZIGBEE_BIND_STATE "ZbBindState"
|
||||
#define D_CMND_ZIGBEE_PING "Ping"
|
||||
#define D_JSON_ZIGBEE_PING "ZbPing"
|
||||
#define D_JSON_ZIGBEE_IEEE "IEEEAddr"
|
||||
|
|
|
@ -399,14 +399,14 @@ String getZigbeeStatusMessage(uint8_t status) {
|
|||
"|UNSUP_MANUF_CLUSTER_COMMAND|UNSUP_MANUF_GENERAL_COMMAND|INVALID_FIELD|UNSUPPORTED_ATTRIBUTE|INVALID_VALE|READ_ONLY"
|
||||
"|INSUFFICIENT_SPACE|DUPLICATE_EXISTS|NOT_FOUND|UNREPORTABLE_ATTRIBUTE|INVALID_DATA_TYPE|INVALID_SELECTOR|WRITE_ONLY"
|
||||
"|INCONSISTENT_STARTUP_STATE|DEFINED_OUT_OF_BAND|INCONSISTENT|ACTION_DENIED|TIMEOUT|ABORT|INVALID_IMAGE|WAIT_FOR_DATA"
|
||||
"|NO_IMAGE_AVAILABLE|REQUIRE_MORE_IMAGE|NOTIFICATION_PENDING|HARDWARE_FAILURE|SOFTWARE_FAILURE|CALIBRATION_ERROR|UNSUPPORTED_CLUSTER"
|
||||
"|NO_IMAGE_AVAILABLE|REQUIRE_MORE_IMAGE|NOTIFICATION_PENDING|HARDWARE_FAILURE|SOFTWARE_FAILURE|CALIBRATION_ERROR|UNSUPPORTED_CLUSTER|NO_ROUTE"
|
||||
"|CHANNEL_ACCESS_FAILURE|NO_ACK|NO_APP_ACK|NO_ROUTE"
|
||||
;
|
||||
static const uint8_t StatusIdx[] PROGMEM = { 0x00, 0x01, 0x7E, 0x7F, 0x80, 0x81, 0x82,
|
||||
0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
|
||||
0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
||||
0x98, 0x99, 0x9A, 0xC0, 0xC1, 0xC2, 0xC3,
|
||||
0x98, 0x99, 0x9A, 0xC0, 0xC1, 0xC2, 0xC3, 0xCD,
|
||||
0xE1, 0xE9, 0xA7, 0xD0};
|
||||
|
||||
char msg[32];
|
||||
|
|
|
@ -130,7 +130,7 @@ void ZigbeeHueGroups(String * lights) {
|
|||
// Send commands
|
||||
// Power On/Off
|
||||
void ZigbeeHuePower(uint16_t shortaddr, bool power) {
|
||||
zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0006, power ? 1 : 0, "");
|
||||
zigbeeZCLSendStr(shortaddr, 0, 0, true, 0, 0x0006, power ? 1 : 0, "");
|
||||
zigbee_devices.updateHueState(shortaddr, &power, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@ void ZigbeeHueDimmer(uint16_t shortaddr, uint8_t dimmer) {
|
|||
if (dimmer > 0xFE) { dimmer = 0xFE; }
|
||||
char param[8];
|
||||
snprintf_P(param, sizeof(param), PSTR("%02X0A00"), dimmer);
|
||||
zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0008, 0x04, param);
|
||||
zigbeeZCLSendStr(shortaddr, 0, 0, true, 0, 0x0008, 0x04, param);
|
||||
zigbee_devices.updateHueState(shortaddr, nullptr, nullptr, &dimmer, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
|
@ -150,7 +150,7 @@ void ZigbeeHueCT(uint16_t shortaddr, uint16_t ct) {
|
|||
char param[12];
|
||||
snprintf_P(param, sizeof(param), PSTR("%02X%02X0A00"), ct & 0xFF, ct >> 8);
|
||||
uint8_t colormode = 2; // "ct"
|
||||
zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0300, 0x0A, param);
|
||||
zigbeeZCLSendStr(shortaddr, 0, 0, true, 0, 0x0300, 0x0A, param);
|
||||
zigbee_devices.updateHueState(shortaddr, nullptr, &colormode, nullptr, nullptr, &ct, nullptr, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
|
@ -161,7 +161,7 @@ void ZigbeeHueXY(uint16_t shortaddr, uint16_t x, uint16_t y) {
|
|||
if (y > 0xFEFF) { y = 0xFEFF; }
|
||||
snprintf_P(param, sizeof(param), PSTR("%02X%02X%02X%02X0A00"), x & 0xFF, x >> 8, y & 0xFF, y >> 8);
|
||||
uint8_t colormode = 1; // "xy"
|
||||
zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0300, 0x07, param);
|
||||
zigbeeZCLSendStr(shortaddr, 0, 0, true, 0, 0x0300, 0x07, param);
|
||||
zigbee_devices.updateHueState(shortaddr, nullptr, &colormode, nullptr, nullptr, nullptr, nullptr, &x, &y, nullptr);
|
||||
}
|
||||
|
||||
|
@ -172,7 +172,7 @@ void ZigbeeHueHS(uint16_t shortaddr, uint16_t hue, uint8_t sat) {
|
|||
if (sat > 0xFE) { sat = 0xFE; }
|
||||
snprintf_P(param, sizeof(param), PSTR("%02X%02X0000"), hue8, sat);
|
||||
uint8_t colormode = 0; // "hs"
|
||||
zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0300, 0x06, param);
|
||||
zigbeeZCLSendStr(shortaddr, 0, 0, true, 0, 0x0300, 0x06, param);
|
||||
zigbee_devices.updateHueState(shortaddr, nullptr, &colormode, nullptr, &sat, nullptr, &hue, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
|
|
|
@ -202,13 +202,6 @@ uint32_t parseSingleAttribute(JsonObject& json, char *attrid_str, class SBuffer
|
|||
case 0xFF: // unk
|
||||
break;
|
||||
case 0x10: // bool
|
||||
{
|
||||
uint8_t val_bool = buf.get8(i++);
|
||||
if (0xFF != val_bool) {
|
||||
json[attrid_str] = (bool) (val_bool ? true : false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x20: // uint8
|
||||
case 0x30: // enum8
|
||||
{
|
||||
|
|
|
@ -169,7 +169,7 @@ int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t clus
|
|||
break;
|
||||
}
|
||||
if (attrs) {
|
||||
ZigbeeZCLSend_Raw(shortaddr, groupaddr, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, true /* we do want a response */, zigbee_devices.getNextSeqNumber(shortaddr));
|
||||
ZigbeeZCLSend_Raw(shortaddr, groupaddr, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, 0, attrs, attrs_len, true /* we do want a response */, zigbee_devices.getNextSeqNumber(shortaddr));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -306,10 +306,10 @@ void sendHueUpdate(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uin
|
|||
}
|
||||
if (z_cat >= 0) {
|
||||
uint8_t endpoint = 0;
|
||||
if (!groupaddr) {
|
||||
if (shortaddr) {
|
||||
endpoint = zigbee_devices.findFirstEndpoint(shortaddr);
|
||||
}
|
||||
if ((endpoint) || (groupaddr)) { // send only if we know the endpoint
|
||||
if ((!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
|
||||
zigbee_devices.setTimer(shortaddr, groupaddr, wait_ms + Z_CAT_REACHABILITY_TIMEOUT, cluster, endpoint, Z_CAT_REACHABILITY, 0 /* value */, &Z_Unreachable);
|
||||
|
|
|
@ -56,7 +56,7 @@ typedef struct Zigbee_Instruction_Type {
|
|||
} Zigbee_Instruction_Type;
|
||||
|
||||
enum Zigbee_StateMachine_Instruction_Set {
|
||||
// 2 bytes instructions
|
||||
// 4 bytes instructions
|
||||
ZGB_INSTR_4_BYTES = 0,
|
||||
ZGB_INSTR_NOOP = 0, // do nothing
|
||||
ZGB_INSTR_LABEL, // define a label
|
||||
|
@ -67,7 +67,7 @@ enum Zigbee_StateMachine_Instruction_Set {
|
|||
ZGB_INSTR_WAIT_FOREVER, // wait forever but state machine still active
|
||||
ZGB_INSTR_STOP, // stop state machine with optional error code
|
||||
|
||||
// 6 bytes instructions
|
||||
// 8 bytes instructions
|
||||
ZGB_INSTR_8_BYTES = 0x80,
|
||||
ZGB_INSTR_CALL = 0x80, // call a function
|
||||
ZGB_INSTR_LOG, // log a message, if more detailed logging required, call a function
|
||||
|
@ -77,7 +77,7 @@ enum Zigbee_StateMachine_Instruction_Set {
|
|||
ZGB_INSTR_WAIT_RECV, // wait for a message according to the filter
|
||||
ZGB_ON_RECV_UNEXPECTED, // function to handle unexpected messages, or nullptr
|
||||
|
||||
// 10 bytes instructions
|
||||
// 12 bytes instructions
|
||||
ZGB_INSTR_12_BYTES = 0xF0,
|
||||
ZGB_INSTR_WAIT_RECV_CALL, // wait for a filtered message and call function upon receive
|
||||
};
|
||||
|
|
|
@ -388,6 +388,7 @@ int32_t Z_BindRsp(int32_t res, const class SBuffer &buf) {
|
|||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
// Handle Unbind Rsp incoming message
|
||||
//
|
||||
|
@ -413,6 +414,72 @@ int32_t Z_UnbindRsp(int32_t res, const class SBuffer &buf) {
|
|||
|
||||
return -1;
|
||||
}
|
||||
//
|
||||
// Handle MgMt Bind Rsp incoming message
|
||||
//
|
||||
int32_t Z_MgmtBindRsp(int32_t res, const class SBuffer &buf) {
|
||||
uint16_t shortaddr = buf.get16(2);
|
||||
uint8_t status = buf.get8(4);
|
||||
uint8_t bind_total = buf.get8(5);
|
||||
uint8_t bind_start = buf.get8(6);
|
||||
uint8_t bind_len = buf.get8(7);
|
||||
|
||||
const char * friendlyName = zigbee_devices.getFriendlyName(shortaddr);
|
||||
|
||||
Response_P(PSTR("{\"" D_JSON_ZIGBEE_BIND_STATE "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), shortaddr);
|
||||
if (friendlyName) {
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""), friendlyName);
|
||||
}
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_STATUS "\":%d"
|
||||
",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\""
|
||||
",\"BindingsTotal\":%d"
|
||||
//",\"BindingsStart\":%d"
|
||||
",\"Bindings\":["
|
||||
), status, getZigbeeStatusMessage(status).c_str(), bind_total);
|
||||
|
||||
uint32_t idx = 8;
|
||||
for (uint32_t i = 0; i < bind_len; i++) {
|
||||
if (idx + 14 > buf.len()) { break; } // overflow, frame size is between 14 and 21
|
||||
|
||||
//uint64_t srcaddr = buf.get16(idx); // unused
|
||||
uint8_t srcep = buf.get8(idx + 8);
|
||||
uint8_t cluster = buf.get16(idx + 9);
|
||||
uint8_t addrmode = buf.get8(idx + 11);
|
||||
uint16_t group = 0x0000;
|
||||
uint64_t dstaddr = 0;
|
||||
uint8_t dstep = 0x00;
|
||||
if (Z_Addr_Group == addrmode) { // Group address mode
|
||||
group = buf.get16(idx + 12);
|
||||
idx += 14;
|
||||
} else if (Z_Addr_IEEEAddress == addrmode) { // IEEE address mode
|
||||
dstaddr = buf.get64(idx + 12);
|
||||
dstep = buf.get8(idx + 20);
|
||||
idx += 21;
|
||||
} else {
|
||||
//AddLog_P2(LOG_LEVEL_INFO, PSTR("Z_MgmtBindRsp unknwon address mode %d"), addrmode);
|
||||
break; // abort for any other value since we don't know the length of the field
|
||||
}
|
||||
|
||||
if (i > 0) {
|
||||
ResponseAppend_P(PSTR(","));
|
||||
}
|
||||
ResponseAppend_P(PSTR("{\"Cluster\":\"0x%04X\",\"Endpoint\":%d,"), cluster, srcep);
|
||||
if (Z_Addr_Group == addrmode) { // Group address mode
|
||||
ResponseAppend_P(PSTR("\"ToGroup\":%d}"), group);
|
||||
} else if (Z_Addr_IEEEAddress == addrmode) { // IEEE address mode
|
||||
char hex[20];
|
||||
Uint64toHex(dstaddr, hex, 64);
|
||||
ResponseAppend_P(PSTR("\"ToDevice\":\"0x%s\",\"ToEndpoint\":%d}"), hex, dstep);
|
||||
}
|
||||
}
|
||||
|
||||
ResponseAppend_P(PSTR("]}}"));
|
||||
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_BIND_STATE));
|
||||
XdrvRulesProcess();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Send specific ZNP messages
|
||||
|
@ -579,6 +646,7 @@ ZBM(AREQ_ZDO_SIMPLEDESCRSP, Z_AREQ | Z_ZDO, ZDO_SIMPLE_DESC_RSP) // 4
|
|||
ZBM(AREQ_ZDO_IEEE_ADDR_RSP, Z_AREQ | Z_ZDO, ZDO_IEEE_ADDR_RSP) // 4581
|
||||
ZBM(AREQ_ZDO_BIND_RSP, Z_AREQ | Z_ZDO, ZDO_BIND_RSP) // 45A1
|
||||
ZBM(AREQ_ZDO_UNBIND_RSP, Z_AREQ | Z_ZDO, ZDO_UNBIND_RSP) // 45A2
|
||||
ZBM(AREQ_ZDO_MGMT_BIND_RSP, Z_AREQ | Z_ZDO, ZDO_MGMT_BIND_RSP) // 45B3
|
||||
|
||||
// Dispatcher callbacks table
|
||||
const Z_Dispatcher Z_DispatchTable[] PROGMEM = {
|
||||
|
@ -592,6 +660,7 @@ const Z_Dispatcher Z_DispatchTable[] PROGMEM = {
|
|||
{ AREQ_ZDO_IEEE_ADDR_RSP, &Z_ReceiveIEEEAddr },
|
||||
{ AREQ_ZDO_BIND_RSP, &Z_BindRsp },
|
||||
{ AREQ_ZDO_UNBIND_RSP, &Z_UnbindRsp },
|
||||
{ AREQ_ZDO_MGMT_BIND_RSP, &Z_MgmtBindRsp },
|
||||
};
|
||||
|
||||
/*********************************************************************************************\
|
||||
|
@ -643,6 +712,7 @@ void Z_Query_Bulb(uint16_t shortaddr, uint32_t &wait_ms) {
|
|||
zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, wait_ms, 0x0300, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback);
|
||||
wait_ms += inter_message_ms;
|
||||
zigbee_devices.setTimer(shortaddr, 0, wait_ms + Z_CAT_REACHABILITY_TIMEOUT, 0, endpoint, Z_CAT_REACHABILITY, 0 /* value */, &Z_Unreachable);
|
||||
wait_ms += 1000; // wait 1 second between devices
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" // prefix
|
|||
D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|"
|
||||
D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|"
|
||||
D_CMND_ZIGBEE_BIND "|" D_CMND_ZIGBEE_UNBIND "|" D_CMND_ZIGBEE_PING "|" D_CMND_ZIGBEE_MODELID "|"
|
||||
D_CMND_ZIGBEE_LIGHT "|" D_CMND_ZIGBEE_RESTORE
|
||||
D_CMND_ZIGBEE_LIGHT "|" D_CMND_ZIGBEE_RESTORE "|" D_CMND_ZIGBEE_BIND_STATE
|
||||
;
|
||||
|
||||
void (* const ZigbeeCommand[])(void) PROGMEM = {
|
||||
|
@ -44,7 +44,7 @@ void (* const ZigbeeCommand[])(void) PROGMEM = {
|
|||
&CmndZbProbe, &CmndZbRead, &CmndZbZNPReceive,
|
||||
&CmndZbForget, &CmndZbSave, &CmndZbName,
|
||||
&CmndZbBind, &CmndZbUnbind, &CmndZbPing, &CmndZbModelId,
|
||||
&CmndZbLight, CmndZbRestore,
|
||||
&CmndZbLight, &CmndZbRestore, &CmndZbBindState,
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -294,12 +294,12 @@ void ZigbeeZNPSend(const uint8_t *msg, size_t len) {
|
|||
// - transacId: 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(uint16_t shortaddr, uint16_t groupaddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool needResponse, uint8_t transacId) {
|
||||
void ZigbeeZCLSend_Raw(uint16_t shortaddr, uint16_t groupaddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, uint16_t manuf, const uint8_t *msg, size_t len, bool needResponse, uint8_t transacId) {
|
||||
|
||||
SBuffer buf(32+len);
|
||||
buf.add8(Z_SREQ | Z_AF); // 24
|
||||
buf.add8(AF_DATA_REQUEST_EXT); // 02
|
||||
if (groupaddr) {
|
||||
if (0x0000 == 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
|
||||
|
@ -315,8 +315,11 @@ void ZigbeeZCLSend_Raw(uint16_t shortaddr, uint16_t groupaddr, uint16_t clusterI
|
|||
buf.add8(0x30); // 30 options
|
||||
buf.add8(0x1E); // 1E radius
|
||||
|
||||
buf.add16(3 + len);
|
||||
buf.add8((needResponse ? 0x00 : 0x10) | (clusterSpecific ? 0x01 : 0x00)); // Frame Control Field
|
||||
buf.add16(3 + len + (manuf ? 2 : 0));
|
||||
buf.add8((needResponse ? 0x00 : 0x10) | (clusterSpecific ? 0x01 : 0x00) | (manuf ? 0x04 : 0x00)); // Frame Control Field
|
||||
if (manuf) {
|
||||
buf.add16(manuf); // add Manuf Id if not null
|
||||
}
|
||||
buf.add8(transacId); // Transaction Sequance Number
|
||||
buf.add8(cmdId);
|
||||
if (len > 0) {
|
||||
|
@ -342,7 +345,7 @@ void ZigbeeZCLSend_Raw(uint16_t shortaddr, uint16_t groupaddr, uint16_t clusterI
|
|||
// - param: pointer to HEX string for payload, should not be nullptr
|
||||
// Returns: None
|
||||
//
|
||||
void zigbeeZCLSendStr(uint16_t shortaddr, uint16_t groupaddr, uint8_t endpoint, bool clusterSpecific,
|
||||
void zigbeeZCLSendStr(uint16_t shortaddr, uint16_t groupaddr, uint8_t endpoint, bool clusterSpecific, uint16_t manuf,
|
||||
uint16_t cluster, uint8_t cmd, const char *param) {
|
||||
size_t size = param ? strlen(param) : 0;
|
||||
SBuffer buf((size+2)/2); // actual bytes buffer for data
|
||||
|
@ -368,7 +371,7 @@ void zigbeeZCLSendStr(uint16_t shortaddr, uint16_t groupaddr, uint8_t endpoint,
|
|||
}
|
||||
|
||||
// everything is good, we can send the command
|
||||
ZigbeeZCLSend_Raw(shortaddr, groupaddr, cluster, endpoint, cmd, clusterSpecific, buf.getBuffer(), buf.len(), true, zigbee_devices.getNextSeqNumber(shortaddr));
|
||||
ZigbeeZCLSend_Raw(shortaddr, groupaddr, cluster, endpoint, cmd, clusterSpecific, manuf, buf.getBuffer(), buf.len(), true, zigbee_devices.getNextSeqNumber(shortaddr));
|
||||
// now set the timer, if any, to read back the state later
|
||||
if (clusterSpecific) {
|
||||
zigbeeSetCommandTimer(shortaddr, groupaddr, cluster, endpoint);
|
||||
|
@ -397,9 +400,10 @@ void CmndZbSend(void) {
|
|||
|
||||
// params
|
||||
static char delim[] = ", "; // delimiters for parameters
|
||||
uint16_t device = 0x0000; // 0xFFFF is broadcast, so considered valid
|
||||
uint16_t groupaddr = 0x0000; // ignore group address if 0x0000
|
||||
uint16_t device = 0x0000; // 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
|
||||
// Command elements
|
||||
uint16_t cluster = 0;
|
||||
uint8_t cmd = 0;
|
||||
|
@ -408,19 +412,25 @@ void CmndZbSend(void) {
|
|||
bool clusterSpecific = true;
|
||||
|
||||
// parse JSON
|
||||
const JsonVariant &val_group = getCaseInsensitive(json, PSTR("Group"));
|
||||
if (nullptr != &val_group) { groupaddr = strToUInt(val_group); }
|
||||
if (0x0000 == groupaddr) { // if no group address, we need a device address
|
||||
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 ((nullptr == &val_device) || (0x0000 == device)) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||
if (0x0000 == 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);
|
||||
} else { // no device nor group
|
||||
ResponseCmndChar_P(PSTR("Unknown device"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint"));
|
||||
if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); }
|
||||
const JsonVariant &val_manuf = getCaseInsensitive(json, PSTR("Manuf"));
|
||||
if (nullptr != &val_manuf) { manuf = strToUInt(val_manuf); }
|
||||
const JsonVariant &val_cmd = getCaseInsensitive(json, PSTR("Send"));
|
||||
if (nullptr != &val_cmd) {
|
||||
// probe the type of the argument
|
||||
|
@ -523,7 +533,7 @@ void CmndZbSend(void) {
|
|||
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZigbeeZCLSend device: 0x%04X, group: 0x%04X, endpoint:%d, cluster:0x%04X, cmd:0x%02X, send:\"%s\""),
|
||||
device, groupaddr, endpoint, cluster, cmd, cmd_s);
|
||||
zigbeeZCLSendStr(device, groupaddr, endpoint, clusterSpecific, cluster, cmd, cmd_s);
|
||||
zigbeeZCLSendStr(device, groupaddr, endpoint, clusterSpecific, manuf, cluster, cmd, cmd_s);
|
||||
ResponseCmndDone();
|
||||
} else {
|
||||
Response_P(PSTR("Missing zigbee 'Send'"));
|
||||
|
@ -639,6 +649,26 @@ void CmndZbUnbind(void) {
|
|||
ZbBindUnbind(true);
|
||||
}
|
||||
|
||||
//
|
||||
// Command `ZbBindState`
|
||||
//
|
||||
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; }
|
||||
|
||||
SBuffer buf(10);
|
||||
buf.add8(Z_SREQ | Z_ZDO); // 25
|
||||
buf.add8(ZDO_MGMT_BIND_REQ); // 33
|
||||
buf.add16(shortaddr); // shortaddr
|
||||
buf.add8(0); // StartIndex = 0
|
||||
|
||||
ZigbeeZNPSend(buf.getBuffer(), buf.len());
|
||||
|
||||
ResponseCmndDone();
|
||||
}
|
||||
|
||||
// Probe a specific device to get its endpoints and supported clusters
|
||||
void CmndZbProbe(void) {
|
||||
CmndZbProbeOrPing(true);
|
||||
|
@ -865,24 +895,31 @@ void CmndZbRead(void) {
|
|||
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
|
||||
uint16_t manuf = 0x0000; // Manuf Id in ZCL frame
|
||||
size_t attrs_len = 0;
|
||||
uint8_t* attrs = nullptr; // empty string is valid
|
||||
|
||||
const JsonVariant &val_group = getCaseInsensitive(json, PSTR("Group"));
|
||||
if (nullptr != &val_group) { groupaddr = strToUInt(val_group); }
|
||||
if (0x0000 == groupaddr) { // if no group address, we need a device address
|
||||
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 ((nullptr == &val_device) || (0x0000 == device)) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||
if (0x0000 == 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);
|
||||
} else { // no device nor group
|
||||
ResponseCmndChar_P(PSTR("Unknown device"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const JsonVariant &val_cluster = getCaseInsensitive(json, PSTR("Cluster"));
|
||||
if (nullptr != &val_cluster) { cluster = strToUInt(val_cluster); }
|
||||
const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint"));
|
||||
if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); }
|
||||
const JsonVariant &val_manuf = getCaseInsensitive(json, PSTR("Manuf"));
|
||||
if (nullptr != &val_manuf) { manuf = strToUInt(val_manuf); }
|
||||
|
||||
const JsonVariant &val_attr = getCaseInsensitive(json, PSTR("Read"));
|
||||
if (nullptr != &val_attr) {
|
||||
|
@ -910,12 +947,12 @@ void CmndZbRead(void) {
|
|||
endpoint = zigbee_devices.findFirstEndpoint(device);
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint);
|
||||
}
|
||||
if (groupaddr) {
|
||||
if (0x0000 == device) {
|
||||
endpoint = 0xFF; // endpoint not used for group addresses
|
||||
}
|
||||
|
||||
if ((0 != endpoint) && (attrs_len > 0)) {
|
||||
ZigbeeZCLSend_Raw(device, groupaddr, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, true /* we do want a response */, zigbee_devices.getNextSeqNumber(device));
|
||||
ZigbeeZCLSend_Raw(device, groupaddr, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, manuf, attrs, attrs_len, true /* we do want a response */, zigbee_devices.getNextSeqNumber(device));
|
||||
ResponseCmndDone();
|
||||
} else {
|
||||
ResponseCmndChar_P(PSTR("Missing parameters"));
|
||||
|
|
Loading…
Reference in New Issue