mirror of https://github.com/arendst/Tasmota.git
Zigbee prepare for Green Power support
This commit is contained in:
parent
db87f8e8d5
commit
7fb00daa52
|
@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file.
|
|||
- Support for Modbus writing using ModbusBridge by JeroenSt (#16351)
|
||||
- Support for Ethernet in ESP32 safeboot firmware (#16388)
|
||||
- Flowrate meter flow amount/duration, show values in table format (#16385)
|
||||
- Zigbee prepare for Green Power support
|
||||
|
||||
### Changed
|
||||
- TasmotaModbus library from v3.5.0 to v3.6.0 (#16351)
|
||||
|
|
|
@ -923,6 +923,8 @@ enum Z_App_Profiles {
|
|||
Z_PROF_TA = 0x0107, // Telecom Applications
|
||||
Z_PROF_PHHC = 0x0108, // Personal Home & Hospital Care
|
||||
Z_PROF_AMI = 0x0109, // Advanced Metering Initiative
|
||||
// Green Power
|
||||
Z_PROF_GP = 0xa1e0, // Green Power profile
|
||||
};
|
||||
|
||||
enum Z_Device_Ids {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -187,8 +187,8 @@ const uint8_t Z_EXPORT_DATA = 0x80;
|
|||
enum Cx_cluster_short {
|
||||
Cx0000, Cx0001, Cx0002, Cx0003, Cx0004, Cx0005, Cx0006, Cx0007,
|
||||
Cx0008, Cx0009, Cx000A, Cx000B, Cx000C, Cx000D, Cx000E, Cx000F,
|
||||
Cx0010, Cx0011, Cx0012, Cx0013, Cx0014, Cx001A, Cx0020, Cx0100,
|
||||
Cx0101, Cx0102, Cx0201, Cx0202, Cx0203, Cx0204,
|
||||
Cx0010, Cx0011, Cx0012, Cx0013, Cx0014, Cx001A, Cx0020, Cx0021,
|
||||
Cx0100, Cx0101, Cx0102, Cx0201, Cx0202, Cx0203, Cx0204,
|
||||
Cx0300, Cx0301, Cx0400, Cx0401, Cx0402, Cx0403,
|
||||
Cx0404, Cx0405, Cx0406, Cx0500, Cx0702, Cx0B01, Cx0B04, Cx0B05,
|
||||
CxEF00, CxFC01, CxFC40, CxFCC0, CxFCCC,
|
||||
|
@ -197,8 +197,8 @@ enum Cx_cluster_short {
|
|||
const uint16_t Cx_cluster[] PROGMEM = {
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
|
||||
0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x001A, 0x0020, 0x0100,
|
||||
0x0101, 0x0102, 0x0201, 0x0202, 0x0203, 0x0204,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x001A, 0x0020, 0x0021,
|
||||
0x0100, 0x0101, 0x0102, 0x0201, 0x0202, 0x0203, 0x0204,
|
||||
0x0300, 0x0301, 0x0400, 0x0401, 0x0402, 0x0403,
|
||||
0x0404, 0x0405, 0x0406, 0x0500, 0x0702, 0x0B01, 0x0B04, 0x0B05,
|
||||
0xEF00, 0xFC01, 0xFC40, 0xFCC0, 0xFCCC,
|
||||
|
@ -746,6 +746,27 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = {
|
|||
{ Zuint32, Cx0020, 0x0005, Z_(LongPollIntervalMin), Cm1, 0 },
|
||||
{ Zuint16, Cx0020, 0x0006, Z_(FastPollTimeoutMax), Cm1, 0 },
|
||||
|
||||
// Green Power
|
||||
{ Zuint8, Cx0021, 0x0000, Z_(MaxSinkTableEntries), Cm1, 0 },
|
||||
{ Zoctstr16,Cx0021, 0x0001, Z_(SinkTable), Cm1, 0 },
|
||||
{ Zmap8, Cx0021, 0x0002, Z_(CommunicationMode), Cm1, 0 },
|
||||
{ Zmap8, Cx0021, 0x0003, Z_(CcommissioningExitMode),Cm1, 0 },
|
||||
{ Zuint16, Cx0021, 0x0004, Z_(CommissioningWindow), Cm1, 0 },
|
||||
{ Zmap8, Cx0021, 0x0005, Z_(SecurityLevel), Cm1, 0 },
|
||||
{ Zmap24, Cx0021, 0x0006, Z_(ServerFunctionality), Cm1, 0 },
|
||||
{ Zmap24, Cx0021, 0x0007, Z_(ServerActiveFunctionality), Cm1, 0 },
|
||||
{ Zuint8, Cx0021, 0x0010, Z_(MaxProxyTableEntries), Cm1, 0 },
|
||||
{ Zoctstr16,Cx0021, 0x0011, Z_(ProxyTable), Cm1, 0 },
|
||||
{ Zuint8, Cx0021, 0x0012, Z_(NotificationRetryNumber),Cm1, 0 },
|
||||
{ Zuint8, Cx0021, 0x0013, Z_(NotificationRetryTimer),Cm1, 0 },
|
||||
{ Zuint8, Cx0021, 0x0014, Z_(MaxSearchCounter), Cm1, 0 },
|
||||
{ Zoctstr16,Cx0021, 0x0015, Z_(BlockedGPDID), Cm1, 0 },
|
||||
{ Zmap24, Cx0021, 0x0016, Z_(ClientFunctionality), Cm1, 0 },
|
||||
{ Zmap24, Cx0021, 0x0017, Z_(ClientActiveFunctionality), Cm1, 0 },
|
||||
{ Zmap8, Cx0021, 0x0020, Z_(SharedSecurityKeyType),Cm1, 0 },
|
||||
{ Zkey128, Cx0021, 0x0021, Z_(SharedSecurityKey), Cm1, 0 },
|
||||
{ Zkey128, Cx0021, 0x0022, Z_(LinkKey), Cm1, 0 },
|
||||
|
||||
// Shade Configuration cluster
|
||||
{ Zuint16, Cx0100, 0x0000, Z_(PhysicalClosedLimit), Cm1, 0 },
|
||||
{ Zuint8, Cx0100, 0x0001, Z_(MotorStepSize), Cm1, 0 },
|
||||
|
|
|
@ -108,7 +108,7 @@ public:
|
|||
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),
|
||||
shortaddr(srcaddr), srcendpoint(srcendpoint), dstendpoint(dstendpoint), _wasbroadcast(wasbroadcast),
|
||||
_linkquality(linkquality), _securityuse(securityuse), _seqnumber(seqnumber)
|
||||
{
|
||||
_frame_control.d8 = frame_control;
|
||||
|
@ -128,7 +128,7 @@ public:
|
|||
"\"manuf\":\"0x%04X\",\"transact\":%d,"
|
||||
"\"cmdid\":\"0x%02X\",\"payload\":\"%_B\"}}"),
|
||||
groupaddr, cluster, shortaddr,
|
||||
_srcendpoint, dstendpoint, _wasbroadcast,
|
||||
srcendpoint, dstendpoint, _wasbroadcast,
|
||||
_linkquality, _securityuse, _seqnumber,
|
||||
_frame_control,
|
||||
_frame_control.b.frame_type, _frame_control.b.direction, _frame_control.b.disable_def_resp,
|
||||
|
@ -207,7 +207,7 @@ public:
|
|||
inline uint16_t getClusterId(void) const { return cluster; }
|
||||
inline uint8_t getLinkQuality(void) const { return _linkquality; }
|
||||
inline uint8_t getCmdId(void) const { return cmd; }
|
||||
inline uint16_t getSrcEndpoint(void) const { return _srcendpoint; }
|
||||
inline uint16_t getSrcEndpoint(void) const { return srcendpoint; }
|
||||
const SBuffer &getPayload(void) const { return payload; }
|
||||
uint16_t getManufCode(void) const { return manuf; }
|
||||
|
||||
|
@ -234,9 +234,11 @@ public:
|
|||
bool direct = false; // true if direct, false if discover router
|
||||
bool transacSet = false; // is transac already set
|
||||
|
||||
uint8_t srcendpoint = 0x00; // 0x00 is invalid for the src endpoint
|
||||
bool direction = false; // false = client to server (default), true = server to client (rare)
|
||||
|
||||
// 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;
|
||||
|
@ -531,6 +533,16 @@ uint32_t parseSingleAttribute(Z_attribute & attr, const SBuffer &buf,
|
|||
attr.setUInt(uint16_val);
|
||||
}
|
||||
break;
|
||||
case Zdata24: // data16
|
||||
case Zmap24: // map16
|
||||
{
|
||||
uint32_t uint32_val = buf.get16(i);
|
||||
uint8_t high = buf.get8(i+2);
|
||||
uint32_val = uint32_val | (high << 16);
|
||||
// i += 3;
|
||||
attr.setUInt(uint32_val);
|
||||
}
|
||||
break;
|
||||
case Zdata32: // data32
|
||||
case Zmap32: // map32
|
||||
{
|
||||
|
@ -549,7 +561,7 @@ uint32_t parseSingleAttribute(Z_attribute & attr, const SBuffer &buf,
|
|||
}
|
||||
break;
|
||||
|
||||
// TODO
|
||||
// All other fixed size, convert to a HEX dump
|
||||
case ZToD: // ToD
|
||||
case Zdate: // date
|
||||
case ZclusterId: // clusterId
|
||||
|
@ -558,17 +570,19 @@ uint32_t parseSingleAttribute(Z_attribute & attr, const SBuffer &buf,
|
|||
case ZEUI64: // EUI64
|
||||
case Zkey128: // key128
|
||||
case Zsemi: // semi (float on 2 bytes)
|
||||
{
|
||||
attr.setBuf(buf, i, len);
|
||||
}
|
||||
// i += 16;
|
||||
break;
|
||||
|
||||
// Other un-implemented data types
|
||||
case Zdata24: // data24
|
||||
case Zdata40: // data40
|
||||
case Zdata48: // data48
|
||||
case Zdata56: // data56
|
||||
case Zdata64: // data64
|
||||
break;
|
||||
// map<x>
|
||||
case Zmap24: // map24
|
||||
case Zmap40: // map40
|
||||
case Zmap48: // map48
|
||||
case Zmap56: // map56
|
||||
|
@ -621,7 +635,7 @@ void ZCLFrame::parseReportAttributes(Z_attribute_list& attr_list) {
|
|||
ZCLFrame zcl(2); // message is 2 bytes
|
||||
zcl.shortaddr = shortaddr;
|
||||
zcl.cluster = cluster;
|
||||
zcl.dstendpoint = _srcendpoint;
|
||||
zcl.dstendpoint = srcendpoint;
|
||||
zcl.cmd = ZCL_DEFAULT_RESPONSE;
|
||||
zcl.manuf = manuf;
|
||||
zcl.clusterSpecific = false; /* not cluster specific */
|
||||
|
@ -768,7 +782,7 @@ void ZCLFrame::computeSyntheticAttributes(Z_attribute_list& attr_list) {
|
|||
if (attr_rgb == nullptr) { // make sure we didn't already computed it
|
||||
uint8_t brightness = 255;
|
||||
if (device.valid()) {
|
||||
const Z_Data_Light & light = device.data.find<Z_Data_Light>(_srcendpoint);
|
||||
const Z_Data_Light & light = device.data.find<Z_Data_Light>(srcendpoint);
|
||||
if ((&light != &z_data_unk) && (light.validDimmer())) {
|
||||
// Dimmer has a valid value
|
||||
brightness = changeUIntScale(light.getDimmer(), 0, 254, 0, 255); // range is 0..255
|
||||
|
@ -798,7 +812,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(shortaddr).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());
|
||||
}
|
||||
|
@ -821,12 +835,12 @@ 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(shortaddr).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(shortaddr, 0 /* groupaddr */, pir_timer, cluster, _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(shortaddr, 0 /* groupaddr */, Z_CAT_VIRTUAL_OCCUPANCY);
|
||||
|
@ -1049,7 +1063,7 @@ void ZCLFrame::parseResponse_inner(uint8_t cmd, bool cluster_specific, uint8_t s
|
|||
// "StatusMessage"
|
||||
attr_list.addAttributePMEM(PSTR(D_JSON_ZIGBEE_STATUS_MSG)).setStr(getZigbeeStatusMessage(status).c_str());
|
||||
// Add Endpoint
|
||||
attr_list.addAttributePMEM(PSTR(D_CMND_ZIGBEE_ENDPOINT)).setUInt(_srcendpoint);
|
||||
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;
|
||||
|
@ -1082,16 +1096,16 @@ void Z_ResetDebounce(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, u
|
|||
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(shortaddr);
|
||||
if ((device.debounce_endpoint != 0) && (device.debounce_endpoint == _srcendpoint) && (device.debounce_transact == transactseq)) {
|
||||
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"), shortaddr, _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_endpoint = srcendpoint;
|
||||
device.debounce_transact = transactseq;
|
||||
zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, USE_ZIGBEE_DEBOUNCE_COMMANDS, 0 /*clusterid*/, _srcendpoint, Z_CAT_DEBOUNCE_CMD, 0, &Z_ResetDebounce);
|
||||
zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, USE_ZIGBEE_DEBOUNCE_COMMANDS, 0 /*clusterid*/, srcendpoint, Z_CAT_DEBOUNCE_CMD, 0, &Z_ResetDebounce);
|
||||
|
||||
convertClusterSpecific(attr_list, cluster, cmd, _frame_control.b.direction, shortaddr, _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)
|
||||
|
@ -1107,7 +1121,7 @@ void ZCLFrame::parseClusterSpecificCommand(Z_attribute_list& attr_list) {
|
|||
ZCLFrame zcl(2); // message is 4 bytes
|
||||
zcl.shortaddr = shortaddr;
|
||||
zcl.cluster = cluster;
|
||||
zcl.dstendpoint = _srcendpoint;
|
||||
zcl.dstendpoint = srcendpoint;
|
||||
zcl.cmd = ZCL_DEFAULT_RESPONSE;
|
||||
zcl.manuf = manuf;
|
||||
zcl.clusterSpecific = false; /* not cluster specific */
|
||||
|
|
|
@ -315,16 +315,22 @@ ZBM(ZBR_ZDO_ACTIVEEPREQ, Z_SRSP | Z_ZDO, ZDO_ACTIVE_EP_REQ, Z_SUCCESS) // 65050
|
|||
// Change #14819 - we now allow some EP to be alreaady declared
|
||||
ZBM(ZBR_ZDO_ACTIVEEPRSP_SUCESS, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 /* srcAddr */, Z_SUCCESS) // 45050000xxxx - no Ep running
|
||||
ZBM(ZBR_ZDO_ACTIVEEPRSP_OK, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 /* srcAddr */, Z_SUCCESS,
|
||||
0x00, 0x00 /* nwkaddr */, 0x02 /* activeepcount */, 0x0B, 0x01 /* the actual endpoints */) // 25050000 - no Ep running
|
||||
0x00, 0x00 /* nwkaddr */, 0x03 /* activeepcount */, 0xF2, 0x0B, 0x01 /* the actual endpoints */) // 4585000000000003F20B01
|
||||
|
||||
// Z_AF:register profile:104, ep:01
|
||||
ZBM(ZBS_AF_REGISTER01, Z_SREQ | Z_AF, AF_REGISTER, 0x01 /* endpoint */, Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), // 24000401050000000000
|
||||
0x05, 0x00 /* AppDeviceId */, 0x00 /* AppDevVer */, 0x00 /* LatencyReq */,
|
||||
0x00 /* AppNumInClusters */, 0x00 /* AppNumInClusters */)
|
||||
0x00 /* AppNumInClusters */, 0x00 /* AppNumOutClusters */)
|
||||
ZBM(ZBR_AF_REGISTER, Z_SRSP | Z_AF, AF_REGISTER, Z_SUCCESS) // 640000
|
||||
ZBM(ZBS_AF_REGISTER0B, Z_SREQ | Z_AF, AF_REGISTER, 0x0B /* endpoint */, Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), // 2400040B050000000000
|
||||
0x05, 0x00 /* AppDeviceId */, 0x00 /* AppDevVer */, 0x00 /* LatencyReq */,
|
||||
0x00 /* AppNumInClusters */, 0x00 /* AppNumInClusters */)
|
||||
0x00 /* AppNumInClusters */, 0x00 /* AppNumOutClusters */)
|
||||
// Green Power endpoint 242 0xF2
|
||||
ZBM(ZBS_AF_REGISTERF2, Z_SREQ | Z_AF, AF_REGISTER, 0xF2 /* endpoint */, Z_B0(Z_PROF_GP), Z_B1(Z_PROF_GP), //
|
||||
0x05, 0x61 /* AppDeviceId */, 0x00 /* AppDevVer */, 0x00 /* LatencyReq */,
|
||||
0x00 /* AppNumInClusters */,
|
||||
0x01 /* AppNumOutClusters */,
|
||||
0x21,0x00) // 0x0021
|
||||
// Z_AF:register profile:104, ep:01 - main clusters for router or device
|
||||
ZBM(ZBS_AF_REGISTER_ALL, Z_SREQ | Z_AF, AF_REGISTER, 0x01 /* endpoint */, Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), // 24000401050000000000
|
||||
0x05, 0x00 /* AppDeviceId */, 0x00 /* AppDevVer */, 0x00 /* LatencyReq */,
|
||||
|
@ -333,7 +339,7 @@ ZBM(ZBS_AF_REGISTER_ALL, Z_SREQ | Z_AF, AF_REGISTER, 0x01 /* endpoint */, Z_B0(Z
|
|||
0x07,0x00, 0x08,0x00, 0x0A,0x00, 0x02,0x01, // 0x0007, 0x0008, 0x000A, 0X0102
|
||||
0x00,0x03, 0x00,0x04, 0x02,0x04, 0x03,0x04, // 0x0300, 0x0400, 0x0402, 0x0403
|
||||
0x05,0x04, 0x06,0x04, // 0x0405, 0x0406
|
||||
0x00 /* AppNumInClusters */)
|
||||
0x00 /* AppNumOutClusters */)
|
||||
|
||||
// Z_ZDO:mgmtPermitJoinReq
|
||||
ZBM(ZBS_PERMITJOINREQ_CLOSE, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x02 /* AddrMode */, // 25360200000000
|
||||
|
@ -506,6 +512,8 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
|
|||
ZI_WAIT_RECV(1000, ZBR_AF_REGISTER)
|
||||
ZI_SEND(ZBS_AF_REGISTER0B) // Z_AF register for endpoint 0B, profile 0x0104 Home Automation
|
||||
ZI_WAIT_RECV(1000, ZBR_AF_REGISTER)
|
||||
ZI_SEND(ZBS_AF_REGISTERF2) // Z_AF register for endpoint F2, profile 0xa1e0 Green Power
|
||||
ZI_WAIT_RECV(1000, ZBR_AF_REGISTER)
|
||||
// Write again channels, see https://github.com/Koenkk/zigbee-herdsman/blob/37bea20ba04ee5d4938abc21a7569b43f831de32/src/adapter/z-stack/adapter/startZnp.ts#L244-L245
|
||||
ZI_SEND(ZBS_W_CHANN) // write CHANNEL
|
||||
ZI_WAIT_RECV(1000, ZBR_WNV_OK)
|
||||
|
|
|
@ -2232,7 +2232,7 @@ void ZCLFrame::autoResponder(const uint16_t *attr_list_ids, size_t attr_len) {
|
|||
",\"Endpoint\":%d"
|
||||
",\"Response\":%s}"
|
||||
),
|
||||
shortaddr, cluster, _srcendpoint,
|
||||
shortaddr, cluster, srcendpoint,
|
||||
attr_list.toString().c_str());
|
||||
|
||||
// send
|
||||
|
@ -2240,7 +2240,7 @@ void ZCLFrame::autoResponder(const uint16_t *attr_list_ids, size_t attr_len) {
|
|||
ZCLFrame zcl(buf.len()); // message is 4 bytes
|
||||
zcl.shortaddr = shortaddr;
|
||||
zcl.cluster = cluster;
|
||||
zcl.dstendpoint = _srcendpoint;
|
||||
zcl.dstendpoint = srcendpoint;
|
||||
zcl.cmd = ZCL_READ_ATTRIBUTES_RESPONSE;
|
||||
zcl.clusterSpecific = false; /* not cluster specific */
|
||||
zcl.needResponse = false; /* noresponse */
|
||||
|
|
|
@ -775,14 +775,19 @@ void ZigbeeZCLSend_Raw(const ZCLFrame &zcl) {
|
|||
buf.add8(zcl.dstendpoint); // dest endpoint
|
||||
}
|
||||
buf.add16(0x0000); // dest Pan ID, 0x0000 = intra-pan
|
||||
buf.add8(0x01); // source endpoint
|
||||
if (zcl.srcendpoint) {
|
||||
buf.add8(zcl.srcendpoint); // source endpoint
|
||||
} else {
|
||||
buf.add8(1); // set endpoint to 1 if not specified
|
||||
}
|
||||
buf.add16(zcl.cluster);
|
||||
buf.add8(zcl.transactseq); // transactseq
|
||||
buf.add8(0x30); // 30 options
|
||||
buf.add8(zcl.direct ? 0x00 : 0x30); // 30 options
|
||||
buf.add8(0x1E); // 1E radius
|
||||
|
||||
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
|
||||
buf.add8((zcl.needResponse ? 0x00 : 0x10) | (zcl.clusterSpecific ? 0x01 : 0x00) |
|
||||
(zcl.manuf ? 0x04 : 0x00) | (zcl.direction ? 0x08 : 0x00)); // Frame Control Field
|
||||
if (zcl.manuf) {
|
||||
buf.add16(zcl.manuf); // add Manuf Id if not null
|
||||
}
|
||||
|
|
|
@ -730,8 +730,17 @@ void CmndZbSend(void) {
|
|||
// parse "Device" and "Group"
|
||||
JsonParserToken val_device = root[PSTR(D_CMND_ZIGBEE_DEVICE)];
|
||||
if (val_device) {
|
||||
zcl.shortaddr = zigbee_devices.parseDeviceFromName(val_device.getStr()).shortaddr;
|
||||
if (!zcl.validShortaddr()) { ResponseCmndChar_P(PSTR(D_ZIGBEE_INVALID_PARAM)); return; }
|
||||
uint16_t parsed_shortaddr = BAD_SHORTADDR;
|
||||
zcl.shortaddr = zigbee_devices.parseDeviceFromName(val_device.getStr(), &parsed_shortaddr).shortaddr;
|
||||
if (!zcl.validShortaddr()) {
|
||||
if (parsed_shortaddr != BAD_SHORTADDR) {
|
||||
// we still got a short address
|
||||
zcl.shortaddr = parsed_shortaddr;
|
||||
} else {
|
||||
ResponseCmndChar_P(PSTR(D_ZIGBEE_INVALID_PARAM));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!zcl.validShortaddr()) { // if not found, check if we have a group
|
||||
JsonParserToken val_group = root[PSTR(D_CMND_ZIGBEE_GROUP)];
|
||||
|
@ -760,6 +769,10 @@ void CmndZbSend(void) {
|
|||
ResponseCmndChar_P(PSTR("Missing endpoint"));
|
||||
return;
|
||||
}
|
||||
// Special case for Green Power, if dstendpoint is 0xF2, then source endpoint should also be 0xF2
|
||||
if (zcl.dstendpoint == 0xF2) {
|
||||
zcl.srcendpoint = 0xF2;
|
||||
}
|
||||
// from here endpoint is valid and non-zero
|
||||
// cluster may be already specified or 0xFFFF
|
||||
|
||||
|
@ -1517,6 +1530,7 @@ void CmndZbPermitJoin(void) {
|
|||
|
||||
// ZNP Version
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
// put all routers in pairing mode
|
||||
SBuffer buf(34);
|
||||
buf.add8(Z_SREQ | Z_ZDO); // 25
|
||||
buf.add8(ZDO_MGMT_PERMIT_JOIN_REQ); // 36
|
||||
|
@ -1527,6 +1541,22 @@ void CmndZbPermitJoin(void) {
|
|||
|
||||
ZigbeeZNPSend(buf.getBuffer(), buf.len());
|
||||
|
||||
// send Green Power pairing mode
|
||||
ZCLFrame zcl(4); // message is 4 bytes max
|
||||
|
||||
zcl.cmd = 0x02; // GP Proxy Commissioning Mode
|
||||
zcl.cluster = 0x0021; // GP cluster
|
||||
zcl.shortaddr = 0xFFFC; // Broadcast to all routers
|
||||
zcl.srcendpoint = 0xF2; // GP endpoint
|
||||
zcl.dstendpoint = 0xF2; // GP endpoint
|
||||
zcl.needResponse = false; // as per GP spec The Disable default response sub-field of the Frame Control Field of the ZCL header shall be set to 0b1."
|
||||
zcl.clusterSpecific = true; // command
|
||||
zcl.direct = true; // broadcast so no need to discover routes
|
||||
zcl.direction = true; // server to client
|
||||
zcl.payload.add8(0x0B); // Action=1, gpsCommissioningExitMode=0b101 (window expiration + GP Proxy Commissioning Mode)
|
||||
zcl.payload.add16(duration);
|
||||
zigbeeZCLSendCmd(zcl);
|
||||
|
||||
#endif // USE_ZIGBEE_ZNP
|
||||
|
||||
// EZSP VERSION
|
||||
|
|
Loading…
Reference in New Issue