mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-23 10:46:31 +00:00
Merge pull request #9581 from s-hadinger/zigbee_oct_19
Glowing led when permit join
This commit is contained in:
commit
32648da9b6
@ -34,6 +34,7 @@ public:
|
||||
uint16_t manuf;
|
||||
bool clusterSpecific;
|
||||
bool needResponse;
|
||||
bool direct; // true if direct, false if discover router
|
||||
uint8_t transacId; // ZCL transaction number
|
||||
const uint8_t *msg;
|
||||
size_t len;
|
||||
@ -86,6 +87,8 @@ struct ZigbeeStatus {
|
||||
|
||||
ZB_RecvMsgFunc recv_func = nullptr; // function to call when message is expected
|
||||
ZB_RecvMsgFunc recv_unexpected = nullptr; // function called when unexpected message is received
|
||||
|
||||
uint32_t permit_end_time = 0; // timestamp when permit join ends
|
||||
};
|
||||
struct ZigbeeStatus zigbee;
|
||||
SBuffer *zigbee_buffer = nullptr;
|
||||
|
@ -753,6 +753,8 @@ public:
|
||||
void syntheticAqaraCubeOrButton(Z_attribute_list &attr_list, class Z_attribute &attr);
|
||||
void syntheticAqaraVibration(Z_attribute_list &attr_list, class Z_attribute &attr);
|
||||
|
||||
// handle read attributes auto-responder
|
||||
void autoResponder(const uint16_t *attr_list_ids, size_t attr_len);
|
||||
|
||||
inline void setGroupId(uint16_t groupid) {
|
||||
_groupaddr = groupid;
|
||||
@ -1182,6 +1184,7 @@ void ZCLFrame::parseReportAttributes(Z_attribute_list& attr_list) {
|
||||
_manuf_code,
|
||||
false /* not cluster specific */,
|
||||
false /* noresponse */,
|
||||
true /* direct no retry */,
|
||||
_transact_seq, /* zcl transaction id */
|
||||
buf.getBuffer(), buf.len()
|
||||
}));
|
||||
@ -1349,7 +1352,7 @@ void ZCLFrame::parseReadAttributes(Z_attribute_list& attr_list) {
|
||||
attr_list.addAttribute(F("ReadNames")).setStrRaw(attr_names.toString(true).c_str());
|
||||
|
||||
// call auto-responder
|
||||
Z_AutoResponder(_srcaddr, _cluster_id, _srcendpoint, read_attr_ids, len/2);
|
||||
autoResponder(read_attr_ids, len/2);
|
||||
}
|
||||
|
||||
// ZCL_CONFIGURE_REPORTING_RESPONSE
|
||||
|
@ -186,6 +186,7 @@ void Z_ReadAttrCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster
|
||||
0, /* manuf */
|
||||
false /* not cluster specific */,
|
||||
true /* response */,
|
||||
false /* discover route */,
|
||||
seq, /* zcl transaction id */
|
||||
attrs, attrs_len
|
||||
}));
|
||||
|
@ -176,7 +176,7 @@ int32_t EZ_PermitJoinRsp(int32_t res, const class SBuffer &buf) {
|
||||
//
|
||||
// Special case: EZSP does not send an event for PermitJoin end, so we generate a synthetic one
|
||||
//
|
||||
void Z_PermitJoinDisable(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) {
|
||||
void Z_PermitJoinDisable(void) {
|
||||
Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{\"Status\":20,\"Message\":\"Pairing mode disabled\"}}"));
|
||||
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE));
|
||||
}
|
||||
@ -1134,6 +1134,7 @@ void Z_SendDeviceInfoRequest(uint16_t shortaddr) {
|
||||
0x0000, /* manuf */
|
||||
false /* not cluster specific */,
|
||||
true /* response */,
|
||||
false /* discover route */,
|
||||
transacid, /* zcl transaction id */
|
||||
InfoReq, sizeof(InfoReq)
|
||||
}));
|
||||
@ -1155,6 +1156,7 @@ void Z_SendSingleAttributeRead(uint16_t shortaddr, uint16_t groupaddr, uint16_t
|
||||
0x0000, /* manuf */
|
||||
false /* not cluster specific */,
|
||||
true /* response */,
|
||||
false /* discover route */,
|
||||
transacid, /* zcl transaction id */
|
||||
InfoReq, sizeof(InfoReq)
|
||||
}));
|
||||
@ -1301,6 +1303,7 @@ void Z_AutoConfigReportingForCluster(uint16_t shortaddr, uint16_t groupaddr, uin
|
||||
0x0000, /* manuf */
|
||||
false /* not cluster specific */,
|
||||
false /* no response */,
|
||||
false /* discover route */,
|
||||
zigbee_devices.getNextSeqNumber(shortaddr), /* zcl transaction id */
|
||||
buf.buf(), buf.len()
|
||||
}));
|
||||
@ -1779,14 +1782,14 @@ int32_t Z_State_Ready(uint8_t value) {
|
||||
//
|
||||
// Mostly used for routers/end-devices
|
||||
// json: holds the attributes in JSON format
|
||||
void Z_AutoResponder(uint16_t srcaddr, uint16_t cluster, uint8_t endpoint, const uint16_t *attr_list_ids, size_t attr_len) {
|
||||
void ZCLFrame::autoResponder(const uint16_t *attr_list_ids, size_t attr_len) {
|
||||
Z_attribute_list attr_list;
|
||||
|
||||
for (uint32_t i=0; i<attr_len; i++) {
|
||||
uint16_t attr_id = attr_list_ids[i];
|
||||
uint32_t ccccaaaa = (cluster << 16) | attr_id;
|
||||
uint32_t ccccaaaa = (_cluster_id << 16) | attr_id;
|
||||
Z_attribute attr;
|
||||
attr.setKeyId(cluster, attr_id);
|
||||
attr.setKeyId(_cluster_id, attr_id);
|
||||
|
||||
switch (ccccaaaa) {
|
||||
case 0x00000004: attr.setStr(PSTR(USE_ZIGBEE_MANUFACTURER)); break; // Manufacturer
|
||||
@ -1837,7 +1840,7 @@ void Z_AutoResponder(uint16_t srcaddr, uint16_t cluster, uint8_t endpoint, const
|
||||
}
|
||||
if (!attr.isNone()) {
|
||||
Z_parseAttributeKey(attr);
|
||||
attr_list.addAttribute(cluster, attr_id) = attr;
|
||||
attr_list.addAttribute(_cluster_id, attr_id) = attr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1857,22 +1860,22 @@ void Z_AutoResponder(uint16_t srcaddr, uint16_t cluster, uint8_t endpoint, const
|
||||
",\"Endpoint\":%d"
|
||||
",\"Response\":%s}"
|
||||
),
|
||||
srcaddr, cluster, endpoint,
|
||||
_srcaddr, _cluster_id, _srcendpoint,
|
||||
attr_list.toString().c_str());
|
||||
|
||||
// send
|
||||
// all good, send the packet
|
||||
uint8_t seq = zigbee_devices.getNextSeqNumber(srcaddr);
|
||||
ZigbeeZCLSend_Raw(ZigbeeZCLSendMessage({
|
||||
srcaddr,
|
||||
_srcaddr,
|
||||
0x0000,
|
||||
cluster /*cluster*/,
|
||||
endpoint,
|
||||
_cluster_id /*cluster*/,
|
||||
_srcendpoint,
|
||||
ZCL_READ_ATTRIBUTES_RESPONSE,
|
||||
0x0000, /* manuf */
|
||||
false /* not cluster specific */,
|
||||
false /* no response */,
|
||||
seq, /* zcl transaction id */
|
||||
true /* direct response */,
|
||||
_transact_seq, /* zcl transaction id */
|
||||
buf.getBuffer(), buf.len()
|
||||
}));
|
||||
}
|
||||
|
@ -819,7 +819,11 @@ void ZigbeeZCLSend_Raw(const ZigbeeZCLSendMessage &zcl) {
|
||||
buf.add16(zcl.cluster); // cluster
|
||||
buf.add8(0x01); // srcEp
|
||||
buf.add8(zcl.endpoint); // dstEp
|
||||
buf.add16(EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY | EMBER_APS_OPTION_RETRY); // APS frame
|
||||
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.transacId);
|
||||
// end of ApsFrame
|
||||
@ -843,7 +847,11 @@ void ZigbeeZCLSend_Raw(const ZigbeeZCLSendMessage &zcl) {
|
||||
buf.add16(zcl.cluster); // cluster
|
||||
buf.add8(0x01); // srcEp
|
||||
buf.add8(zcl.endpoint); // broadcast endpoint for groupcast
|
||||
buf.add16(EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY | EMBER_APS_OPTION_RETRY); // APS frame
|
||||
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.transacId);
|
||||
// end of ApsFrame
|
||||
|
@ -192,6 +192,7 @@ void zigbeeZCLSendStr(uint16_t shortaddr, uint16_t groupaddr, uint8_t endpoint,
|
||||
manuf, /* manuf */
|
||||
clusterSpecific /* not cluster specific */,
|
||||
true /* response */,
|
||||
false /* discover route */,
|
||||
seq, /* zcl transaction id */
|
||||
buf.getBuffer(), buf.len()
|
||||
}));
|
||||
@ -739,6 +740,7 @@ void CmndZbSend(void) {
|
||||
manuf, /* manuf */
|
||||
false /* not cluster specific */,
|
||||
false /* no response */,
|
||||
false /* discover route */,
|
||||
0, /* zcl transaction id */
|
||||
nullptr, 0
|
||||
});
|
||||
@ -1219,9 +1221,11 @@ void CmndZbPermitJoin(void) {
|
||||
// Log pairing mode enabled
|
||||
Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{\"Status\":21,\"Message\":\"Pairing mode enabled\"}}"));
|
||||
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE));
|
||||
zigbee.permit_end_time = millis() + duration * 1000;
|
||||
AddLog_P2(LOG_LEVEL_INFO, "zigbee.permit_end_time = %d", zigbee.permit_end_time);
|
||||
} else {
|
||||
zigbee.permit_end_time = millis();
|
||||
}
|
||||
// always register timer for disable, might happen at next tick
|
||||
zigbee_devices.setTimer(0x0000 /* coordinator */, 0 /* group addr*/, duration * 1000, 0, 0 /* endpoint */, Z_CAT_PERMIT_JOIN, 0 /* value */, &Z_PermitJoinDisable);
|
||||
#endif // USE_ZIGBEE_EZSP
|
||||
|
||||
ResponseCmndDone();
|
||||
@ -1255,6 +1259,34 @@ void CmndZbEZSPListen(void) {
|
||||
|
||||
ResponseCmndDone();
|
||||
}
|
||||
|
||||
void ZigbeeGlowPermitJoinLight(void) {
|
||||
static const uint16_t cycle_time = 1000; // cycle up and down in 1000 ms
|
||||
static const uint16_t half_cycle_time = cycle_time / 2; // cycle up and down in 1000 ms
|
||||
if (zigbee.permit_end_time) {
|
||||
uint16_t led_power = 0; // turn led off
|
||||
// permit join is ongoing
|
||||
if (TimeReached(zigbee.permit_end_time)) {
|
||||
zigbee.permit_end_time = 0; // disable timer
|
||||
Z_PermitJoinDisable();
|
||||
} else {
|
||||
uint32_t millis_to_go = millis() - zigbee.permit_end_time;
|
||||
uint32_t sub_second = millis_to_go % cycle_time;
|
||||
if (sub_second <= half_cycle_time) {
|
||||
led_power = changeUIntScale(sub_second, 0, half_cycle_time, 0, 1023);
|
||||
} else {
|
||||
led_power = changeUIntScale(sub_second, half_cycle_time, cycle_time, 1023, 0);
|
||||
}
|
||||
led_power = ledGamma10_10(led_power);
|
||||
}
|
||||
|
||||
// change the led state
|
||||
uint32_t led_pin = Pin(GPIO_LEDLNK);
|
||||
if (led_pin < 99) {
|
||||
analogWrite(led_pin, ledlnk_inverted ? 1023 - led_power : led_power);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // USE_ZIGBEE_EZSP
|
||||
|
||||
//
|
||||
@ -1801,6 +1833,9 @@ bool Xdrv23(uint8_t function)
|
||||
if (ZigbeeSerial) {
|
||||
ZigbeeInputLoop();
|
||||
ZigbeeOutputLoop(); // send any outstanding data
|
||||
#ifdef USE_ZIGBEE_EZSP
|
||||
ZigbeeGlowPermitJoinLight();
|
||||
#endif // USE_ZIGBEE_EZSP
|
||||
}
|
||||
if (zigbee.state_machine) {
|
||||
ZigbeeStateMachine_Run();
|
||||
|
Loading…
x
Reference in New Issue
Block a user