mirror of https://github.com/arendst/Tasmota.git
Merge pull request #8825 from s-hadinger/zigbee_ezsp_5
Zigbee EZSP milestone 3
This commit is contained in:
commit
a44f82d072
|
@ -57,7 +57,53 @@ enum ZnpSubsystem {
|
||||||
|
|
||||||
#ifdef USE_ZIGBEE_EZSP
|
#ifdef USE_ZIGBEE_EZSP
|
||||||
|
|
||||||
enum EZSPCondigId {
|
enum EZSPNodeType {
|
||||||
|
EMBER_UNKNOWN_DEVICE = 0x00,
|
||||||
|
EMBER_COORDINATOR = 0x01,
|
||||||
|
EMBER_ROUTER = 0x02,
|
||||||
|
EMBER_END_DEVICE = 0x03,
|
||||||
|
EMBER_SLEEPY_END_DEVICE = 0x04
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EZSPDeviceUpdate {
|
||||||
|
EMBER_STANDARD_SECURITY_SECURED_REJOIN = 0x00,
|
||||||
|
EMBER_STANDARD_SECURITY_UNSECURED_JOIN = 0x01,
|
||||||
|
EMBER_DEVICE_LEFT = 0x02,
|
||||||
|
EMBER_STANDARD_SECURITY_UNSECURED_REJOIN = 0x03,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EZSPJoinDecision {
|
||||||
|
EMBER_USE_PRECONFIGURED_KEY = 0x00,
|
||||||
|
EMBER_SEND_KEY_IN_THE_CLEAR = 0x01,
|
||||||
|
EMBER_DENY_JOIN = 0x02,
|
||||||
|
EMBER_NO_ACTION = 0x03
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EZSPCurrentSecurytBitMask {
|
||||||
|
EMBER_STANDARD_SECURITY_MODE = 0x0000,
|
||||||
|
EMBER_DISTRIBUTED_TRUST_CENTER_MODE = 0x0002,
|
||||||
|
EMBER_GLOBAL_LINK_KEY = 0x0004,
|
||||||
|
EMBER_TRUST_CENTER_GLOBAL_LINK_KEY = 0x0004,
|
||||||
|
EMBER_PRECONFIGURED_NETWORK_KEY_MODE = 0x0008,
|
||||||
|
EMBER_HAVE_TRUST_CENTER_LINK_KEY = 0x0010,
|
||||||
|
EMBER_TRUST_CENTER_USES_HASHED_LINK_KEY = 0x0084,
|
||||||
|
EMBER_HAVE_PRECONFIGURED_KEY = 0x0100,
|
||||||
|
EMBER_HAVE_NETWORK_KEY = 0x0200,
|
||||||
|
EMBER_GET_LINK_KEY_WHEN_JOINING = 0x0400,
|
||||||
|
EMBER_REQUIRE_ENCRYPTED_KEY = 0x0800,
|
||||||
|
EMBER_NO_FRAME_COUNTER_RESET = 0x1000,
|
||||||
|
EMBER_GET_PRECONFIGURED_KEY_FROM_INSTALL_CODE = 0x2000,
|
||||||
|
EMBER_HAVE_TRUST_CENTER_EUI64 = 0x0040
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EZSPJoinMethod {
|
||||||
|
EMBER_USE_MAC_ASSOCIATION = 0x0,
|
||||||
|
EMBER_USE_NWK_REJOIN = 0x1,
|
||||||
|
EMBER_USE_NWK_REJOIN_HAVE_NWK_KEY = 0x2,
|
||||||
|
EMBER_USE_CONFIGURED_NWK_STATE = 0x3
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EZSPConfigId {
|
||||||
EZSP_CONFIG_PACKET_BUFFER_COUNT = 0x01,
|
EZSP_CONFIG_PACKET_BUFFER_COUNT = 0x01,
|
||||||
EZSP_CONFIG_NEIGHBOR_TABLE_SIZE = 0x02,
|
EZSP_CONFIG_NEIGHBOR_TABLE_SIZE = 0x02,
|
||||||
EZSP_CONFIG_APS_UNICAST_MESSAGE_COUNT = 0x03,
|
EZSP_CONFIG_APS_UNICAST_MESSAGE_COUNT = 0x03,
|
||||||
|
@ -301,6 +347,159 @@ enum EZSPStatusId {
|
||||||
EZSP_NO_ERROR = 0xFF
|
EZSP_NO_ERROR = 0xFF
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum EZSPPolicyId {
|
||||||
|
EZSP_TRUST_CENTER_POLICY = 0x00,
|
||||||
|
EZSP_BINDING_MODIFICATION_POLICY = 0x01,
|
||||||
|
EZSP_UNICAST_REPLIES_POLICY = 0x02,
|
||||||
|
EZSP_POLL_HANDLER_POLICY = 0x03,
|
||||||
|
EZSP_MESSAGE_CONTENTS_IN_CALLBACK_POLICY = 0x04,
|
||||||
|
EZSP_TC_KEY_REQUEST_POLICY = 0x05,
|
||||||
|
EZSP_APP_KEY_REQUEST_POLICY = 0x06,
|
||||||
|
EZSP_PACKET_VALIDATE_LIBRARY_POLICY = 0x07,
|
||||||
|
EZSP_ZLL_POLICY = 0x08,
|
||||||
|
EZSP_TC_REJOINS_USING_WELL_KNOWN_KEY_POLICY = 0x09
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EZSPDecisionBitmask {
|
||||||
|
EZSP_DECISION_BITMASK_DEFAULT_CONFIGURATION = 0x0000,
|
||||||
|
EZSP_DECISION_ALLOW_JOINS = 0x0001,
|
||||||
|
EZSP_DECISION_ALLOW_UNSECURED_REJOINS = 0x0002,
|
||||||
|
EZSP_DECISION_SEND_KEY_IN_CLEAR = 0x0004,
|
||||||
|
EZSP_DECISION_IGNORE_UNSECURED_REJOINS = 0x0008,
|
||||||
|
EZSP_DECISION_JOINS_USE_INSTALL_CODE_KEY = 0x0010,
|
||||||
|
EZSP_DECISION_DEFER_JOINS = 0x0020
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EZSPDecisionId {
|
||||||
|
EZSP_DEFER_JOINS_REJOINS_HAVE_LINK_KEY = 0x07,
|
||||||
|
EZSP_DISALLOW_BINDING_MODIFICATION = 0x10,
|
||||||
|
EZSP_ALLOW_BINDING_MODIFICATION = 0x11,
|
||||||
|
EZSP_CHECK_BINDING_MODIFICATIONS_ARE_VALID_ENDPOINT_CLUSTERS = 0x12,
|
||||||
|
EZSP_HOST_WILL_NOT_SUPPLY_REPLY = 0x20,
|
||||||
|
EZSP_HOST_WILL_SUPPLY_REPLY = 0x21,
|
||||||
|
EZSP_POLL_HANDLER_IGNORE = 0x30,
|
||||||
|
EZSP_POLL_HANDLER_CALLBACK = 0x31,
|
||||||
|
EZSP_MESSAGE_TAG_ONLY_IN_CALLBACK = 0x40,
|
||||||
|
EZSP_MESSAGE_TAG_AND_CONTENTS_IN_CALLBACK = 0x41,
|
||||||
|
EZSP_DENY_TC_KEY_REQUESTS = 0x50,
|
||||||
|
EZSP_ALLOW_TC_KEY_REQUESTS_AND_SEND_CURRENT_KEY = 0x51,
|
||||||
|
EZSP_ALLOW_TC_KEY_REQUEST_AND_GENERATE_NEW_KEY = 0x52,
|
||||||
|
EZSP_DENY_APP_KEY_REQUESTS = 0x60,
|
||||||
|
EZSP_ALLOW_APP_KEY_REQUESTS = 0x61,
|
||||||
|
EZSP_PACKET_VALIDATE_LIBRARY_CHECKS_ENABLED = 0x62,
|
||||||
|
EZSP_PACKET_VALIDATE_LIBRARY_CHECKS_DISABLED = 0x63
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EZSP_ZdoConfigurationFlags {
|
||||||
|
EMBER_APP_RECEIVES_SUPPORTED_ZDO_REQUESTS = 0x01,
|
||||||
|
EMBER_APP_HANDLES_UNSUPPORTED_ZDO_REQUESTS = 0x02,
|
||||||
|
EMBER_APP_HANDLES_ZDO_ENDPOINT_REQUESTS = 0x04,
|
||||||
|
EMBER_APP_HANDLES_ZDO_BINDING_REQUESTS = 0x08
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EZSP_EmberIncomingMessageType {
|
||||||
|
EMBER_INCOMING_UNICAST = 0x00,
|
||||||
|
EMBER_INCOMING_UNICAST_REPLY = 0x01,
|
||||||
|
EMBER_INCOMING_MULTICAST = 0x02,
|
||||||
|
EMBER_INCOMING_MULTICAST_LOOPBACK = 0x03,
|
||||||
|
EMBER_INCOMING_BROADCAST = 0x04,
|
||||||
|
EMBER_INCOMING_BROADCAST_LOOPBACK = 0x05,
|
||||||
|
EMBER_INCOMING_MANY_TO_ONE_ROUTE_REQUEST = 0x06
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EZSP_EmberApsOption {
|
||||||
|
EMBER_APS_OPTION_NONE = 0x0000,
|
||||||
|
EMBER_APS_OPTION_ENCRYPTION = 0x0020,
|
||||||
|
EMBER_APS_OPTION_RETRY = 0x0040,
|
||||||
|
EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY = 0x0100,
|
||||||
|
EMBER_APS_OPTION_FORCE_ROUTE_DISCOVERY = 0x0200,
|
||||||
|
EMBER_APS_OPTION_SOURCE_EUI64 = 0x0400,
|
||||||
|
EMBER_APS_OPTION_DESTINATION_EUI64 = 0x0800,
|
||||||
|
EMBER_APS_OPTION_ENABLE_ADDRESS_DISCOVERY = 0x1000,
|
||||||
|
EMBER_APS_OPTION_POLL_RESPONSE = 0x2000,
|
||||||
|
EMBER_APS_OPTION_ZDO_RESPONSE_REQUIRED = 0x4000,
|
||||||
|
EMBER_APS_OPTION_FRAGMENT = 0x8000
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EZSP_EmberOutgoingMessageType {
|
||||||
|
EMBER_OUTGOING_DIRECT = 0x00,
|
||||||
|
EMBER_OUTGOING_VIA_ADDRESS_TABLE = 0x01,
|
||||||
|
EMBER_OUTGOING_VIA_BINDING = 0x02,
|
||||||
|
EMBER_OUTGOING_MULTICAST = 0x03,
|
||||||
|
EMBER_OUTGOING_BROADCAST = 0x04
|
||||||
|
};
|
||||||
|
|
||||||
|
// inspired from https://github.com/zigpy/zigpy/blob/dev/zigpy/zdo/types.py
|
||||||
|
enum EZSP_ZDO {
|
||||||
|
ZDO_NWK_addr_req = 0x0000,
|
||||||
|
ZDO_IEEE_addr_req = 0x0001,
|
||||||
|
ZDO_Node_Desc_req = 0x0002,
|
||||||
|
ZDO_Power_Desc_req = 0x0003,
|
||||||
|
ZDO_Simple_Desc_req = 0x0004,
|
||||||
|
ZDO_Active_EP_req = 0x0005,
|
||||||
|
ZDO_Match_Desc_req = 0x0006,
|
||||||
|
ZDO_Complex_Desc_req = 0x0010,
|
||||||
|
ZDO_User_Desc_req = 0x0011,
|
||||||
|
ZDO_Discovery_Cache_req = 0x0012,
|
||||||
|
ZDO_Device_annce = 0x0013,
|
||||||
|
ZDO_User_Desc_set = 0x0014,
|
||||||
|
ZDO_System_Server_Discovery_req = 0x0015,
|
||||||
|
ZDO_Discovery_store_req = 0x0016,
|
||||||
|
ZDO_Node_Desc_store_req = 0x0017,
|
||||||
|
ZDO_Active_EP_store_req = 0x0019,
|
||||||
|
ZDO_Simple_Desc_store_req = 0x001A,
|
||||||
|
ZDO_Remove_node_cache_req = 0x001B,
|
||||||
|
ZDO_Find_node_cache_req = 0x001C,
|
||||||
|
ZDO_Extended_Simple_Desc_req = 0x001D,
|
||||||
|
ZDO_Extended_Active_EP_req = 0x001E,
|
||||||
|
ZDO_Parent_annce = 0x001F,
|
||||||
|
// Bind Management Server Services Responses
|
||||||
|
ZDO_End_Device_Bind_req = 0x0020,
|
||||||
|
ZDO_Bind_req = 0x0021,
|
||||||
|
ZDO_Unbind_req = 0x0022,
|
||||||
|
// Network Management Server Services Requests
|
||||||
|
ZDO_Mgmt_Lqi_req = 0x0031,
|
||||||
|
ZDO_Mgmt_Rtg_req = 0x0032,
|
||||||
|
ZDO_Mgmt_Leave_req = 0x0034,
|
||||||
|
ZDO_Mgmt_Permit_Joining_req = 0x0036,
|
||||||
|
ZDO_Mgmt_NWK_Update_req = 0x0038,
|
||||||
|
|
||||||
|
// Responses
|
||||||
|
// Device and Service Discovery Server Responses
|
||||||
|
ZDO_NWK_addr_rsp = 0x8000,
|
||||||
|
ZDO_IEEE_addr_rsp = 0x8001,
|
||||||
|
ZDO_Node_Desc_rsp = 0x8002,
|
||||||
|
ZDO_Power_Desc_rsp = 0x8003,
|
||||||
|
ZDO_Simple_Desc_rsp = 0x8004,
|
||||||
|
ZDO_Active_EP_rsp = 0x8005,
|
||||||
|
ZDO_Match_Desc_rsp = 0x8006,
|
||||||
|
ZDO_Complex_Desc_rsp = 0x8010,
|
||||||
|
ZDO_User_Desc_rsp = 0x8011,
|
||||||
|
ZDO_Discovery_Cache_rsp = 0x8012,
|
||||||
|
ZDO_User_Desc_conf = 0x8014,
|
||||||
|
ZDO_System_Server_Discovery_rsp = 0x8015,
|
||||||
|
ZDO_Discovery_Store_rsp = 0x8016,
|
||||||
|
ZDO_Node_Desc_store_rsp = 0x8017,
|
||||||
|
ZDO_Power_Desc_store_rsp = 0x8018,
|
||||||
|
ZDO_Active_EP_store_rsp = 0x8019,
|
||||||
|
ZDO_Simple_Desc_store_rsp = 0x801A,
|
||||||
|
ZDO_Remove_node_cache_rsp = 0x801B,
|
||||||
|
ZDO_Find_node_cache_rsp = 0x801C,
|
||||||
|
ZDO_Extended_Simple_Desc_rsp = 0x801D,
|
||||||
|
ZDO_Extended_Active_EP_rsp = 0x801E,
|
||||||
|
ZDO_Parent_annce_rsp = 0x801F,
|
||||||
|
// Bind Management Server Services Responses
|
||||||
|
ZDO_End_Device_Bind_rsp = 0x8020,
|
||||||
|
ZDO_Bind_rsp = 0x8021,
|
||||||
|
ZDO_Unbind_rsp = 0x8022,
|
||||||
|
// Network Management Server Services Responses
|
||||||
|
ZDO_Mgmt_Lqi_rsp = 0x8031,
|
||||||
|
ZDO_Mgmt_Rtg_rsp = 0x8032,
|
||||||
|
ZDO_Mgmt_Leave_rsp = 0x8034,
|
||||||
|
ZDO_Mgmt_Permit_Joining_rsp = 0x8036,
|
||||||
|
ZDO_Mgmt_NWK_Update_rsp = 0x8038,
|
||||||
|
};
|
||||||
|
|
||||||
enum EZSP_Commands {
|
enum EZSP_Commands {
|
||||||
EZSP_version = 0x0000,
|
EZSP_version = 0x0000,
|
||||||
EZSP_getLibraryStatus = 0x0001,
|
EZSP_getLibraryStatus = 0x0001,
|
||||||
|
|
|
@ -244,6 +244,7 @@ Z_Devices zigbee_devices = Z_Devices();
|
||||||
|
|
||||||
// Local coordinator information
|
// Local coordinator information
|
||||||
uint64_t localIEEEAddr = 0;
|
uint64_t localIEEEAddr = 0;
|
||||||
|
uint16_t localShortAddr = 0;
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Implementation
|
* Implementation
|
||||||
|
|
|
@ -595,14 +595,12 @@ public:
|
||||||
ZCLFrame(uint8_t frame_control, uint16_t manuf_code, uint8_t transact_seq, uint8_t cmd_id,
|
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,
|
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,
|
uint16_t srcaddr, uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast,
|
||||||
uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber,
|
uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber):
|
||||||
uint32_t timestamp):
|
|
||||||
_manuf_code(manuf_code), _transact_seq(transact_seq), _cmd_id(cmd_id),
|
_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
|
_payload(buf_len ? buf_len : 250), // allocate the data frame from source or preallocate big enough
|
||||||
_cluster_id(clusterid), _groupaddr(groupaddr),
|
_cluster_id(clusterid), _groupaddr(groupaddr),
|
||||||
_srcaddr(srcaddr), _srcendpoint(srcendpoint), _dstendpoint(dstendpoint), _wasbroadcast(wasbroadcast),
|
_srcaddr(srcaddr), _srcendpoint(srcendpoint), _dstendpoint(dstendpoint), _wasbroadcast(wasbroadcast),
|
||||||
_linkquality(linkquality), _securityuse(securityuse), _seqnumber(seqnumber),
|
_linkquality(linkquality), _securityuse(securityuse), _seqnumber(seqnumber)
|
||||||
_timestamp(timestamp)
|
|
||||||
{
|
{
|
||||||
_frame_control.d8 = frame_control;
|
_frame_control.d8 = frame_control;
|
||||||
_payload.addBuffer(buf, buf_len);
|
_payload.addBuffer(buf, buf_len);
|
||||||
|
@ -616,13 +614,11 @@ public:
|
||||||
"\"groupid\":%d," "\"clusterid\":%d," "\"srcaddr\":\"0x%04X\","
|
"\"groupid\":%d," "\"clusterid\":%d," "\"srcaddr\":\"0x%04X\","
|
||||||
"\"srcendpoint\":%d," "\"dstendpoint\":%d," "\"wasbroadcast\":%d,"
|
"\"srcendpoint\":%d," "\"dstendpoint\":%d," "\"wasbroadcast\":%d,"
|
||||||
"\"" D_CMND_ZIGBEE_LINKQUALITY "\":%d," "\"securityuse\":%d," "\"seqnumber\":%d,"
|
"\"" D_CMND_ZIGBEE_LINKQUALITY "\":%d," "\"securityuse\":%d," "\"seqnumber\":%d,"
|
||||||
"\"timestamp\":%d,"
|
|
||||||
"\"fc\":\"0x%02X\",\"manuf\":\"0x%04X\",\"transact\":%d,"
|
"\"fc\":\"0x%02X\",\"manuf\":\"0x%04X\",\"transact\":%d,"
|
||||||
"\"cmdid\":\"0x%02X\",\"payload\":\"%s\"}}"),
|
"\"cmdid\":\"0x%02X\",\"payload\":\"%s\"}}"),
|
||||||
_groupaddr, _cluster_id, _srcaddr,
|
_groupaddr, _cluster_id, _srcaddr,
|
||||||
_srcendpoint, _dstendpoint, _wasbroadcast,
|
_srcendpoint, _dstendpoint, _wasbroadcast,
|
||||||
_linkquality, _securityuse, _seqnumber,
|
_linkquality, _securityuse, _seqnumber,
|
||||||
_timestamp,
|
|
||||||
_frame_control, _manuf_code, _transact_seq, _cmd_id,
|
_frame_control, _manuf_code, _transact_seq, _cmd_id,
|
||||||
hex_char);
|
hex_char);
|
||||||
if (Settings.flag3.tuya_serial_mqtt_publish) {
|
if (Settings.flag3.tuya_serial_mqtt_publish) {
|
||||||
|
@ -635,8 +631,7 @@ public:
|
||||||
|
|
||||||
static ZCLFrame parseRawFrame(const SBuffer &buf, uint8_t offset, uint8_t len, uint16_t clusterid, uint16_t groupid,
|
static ZCLFrame parseRawFrame(const SBuffer &buf, uint8_t offset, uint8_t len, uint16_t clusterid, uint16_t groupid,
|
||||||
uint16_t srcaddr, uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast,
|
uint16_t srcaddr, uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast,
|
||||||
uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber,
|
uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber) { // parse a raw frame and build the ZCL frame object
|
||||||
uint32_t timestamp) { // parse a raw frame and build the ZCL frame object
|
|
||||||
uint32_t i = offset;
|
uint32_t i = offset;
|
||||||
ZCLHeaderFrameControl_t frame_control;
|
ZCLHeaderFrameControl_t frame_control;
|
||||||
uint16_t manuf_code = 0;
|
uint16_t manuf_code = 0;
|
||||||
|
@ -654,8 +649,7 @@ public:
|
||||||
(const char *)(buf.buf() + i), len + offset - i,
|
(const char *)(buf.buf() + i), len + offset - i,
|
||||||
clusterid, groupid,
|
clusterid, groupid,
|
||||||
srcaddr, srcendpoint, dstendpoint, wasbroadcast,
|
srcaddr, srcendpoint, dstendpoint, wasbroadcast,
|
||||||
linkquality, securityuse, seqnumber,
|
linkquality, securityuse, seqnumber);
|
||||||
timestamp);
|
|
||||||
return zcl_frame;
|
return zcl_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -679,17 +673,12 @@ public:
|
||||||
_cluster_id = clusterid;
|
_cluster_id = clusterid;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint8_t getCmdId(void) const {
|
inline uint16_t getSrcAddr(void) const { return _srcaddr; }
|
||||||
return _cmd_id;
|
inline uint16_t getGroupAddr(void) const { return _groupaddr; }
|
||||||
}
|
inline uint16_t getClusterId(void) const { return _cluster_id; }
|
||||||
|
inline uint8_t getLinkQuality(void) const { return _linkquality; }
|
||||||
inline uint16_t getClusterId(void) const {
|
inline uint8_t getCmdId(void) const { return _cmd_id; }
|
||||||
return _cluster_id;
|
inline uint16_t getSrcEndpoint(void) const { return _srcendpoint; }
|
||||||
}
|
|
||||||
|
|
||||||
inline uint16_t getSrcEndpoint(void) const {
|
|
||||||
return _srcendpoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SBuffer &getPayload(void) const {
|
const SBuffer &getPayload(void) const {
|
||||||
return _payload;
|
return _payload;
|
||||||
|
@ -699,6 +688,7 @@ public:
|
||||||
return _manuf_code;
|
return _manuf_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ZCLHeaderFrameControl_t _frame_control = { .d8 = 0 };
|
ZCLHeaderFrameControl_t _frame_control = { .d8 = 0 };
|
||||||
uint16_t _manuf_code = 0; // optional
|
uint16_t _manuf_code = 0; // optional
|
||||||
|
@ -715,7 +705,6 @@ private:
|
||||||
uint8_t _linkquality;
|
uint8_t _linkquality;
|
||||||
uint8_t _securityuse;
|
uint8_t _securityuse;
|
||||||
uint8_t _seqnumber;
|
uint8_t _seqnumber;
|
||||||
uint32_t _timestamp;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Zigbee ZCL converters
|
// Zigbee ZCL converters
|
||||||
|
|
|
@ -50,12 +50,15 @@ ZF(HueSat) ZF(Color)
|
||||||
ZF(ShutterOpen) ZF(ShutterClose) ZF(ShutterStop) ZF(ShutterLift) ZF(ShutterTilt) ZF(Shutter)
|
ZF(ShutterOpen) ZF(ShutterClose) ZF(ShutterStop) ZF(ShutterLift) ZF(ShutterTilt) ZF(Shutter)
|
||||||
//ZF(Occupancy)
|
//ZF(Occupancy)
|
||||||
ZF(DimmerMove) ZF(DimmerStep) ZF(DimmerStepUp) ZF(DimmerStepDown)
|
ZF(DimmerMove) ZF(DimmerStep) ZF(DimmerStepUp) ZF(DimmerStepDown)
|
||||||
ZF(HueMove) ZF(HueStep) ZF(HueStepUp) ZF(HueStepDown) ZF(SatMove) ZF(SatStep) ZF(ColorMove) ZF(ColorStep) ZF(ColorTempStep) ZF(ColorTempStepUp) ZF(ColorTempStepDown)
|
ZF(HueMove) ZF(HueStep) ZF(HueStepUp) ZF(HueStepDown) ZF(SatMove) ZF(SatStep) ZF(ColorMove) ZF(ColorStep)
|
||||||
|
ZF(ColorTempMoveUp) ZF(ColorTempMoveDown) ZF(ColorTempMoveStop) ZF(ColorTempMove)
|
||||||
|
ZF(ColorTempStep) ZF(ColorTempStepUp) ZF(ColorTempStepDown)
|
||||||
ZF(ArrowClick) ZF(ArrowHold) ZF(ArrowRelease) ZF(ZoneStatusChange)
|
ZF(ArrowClick) ZF(ArrowHold) ZF(ArrowRelease) ZF(ZoneStatusChange)
|
||||||
|
|
||||||
ZF(xxxx00) ZF(xxxx) ZF(01xxxx) ZF(03xxxx) ZF(00) ZF(01) ZF() ZF(xxxxyy) ZF(00190200) ZF(01190200) ZF(xxyyyy) ZF(xx)
|
ZF(xxxx00) ZF(xxxx) ZF(01xxxx) ZF(03xxxx) ZF(00) ZF(01) ZF() ZF(xxxxyy) ZF(00190200) ZF(01190200) ZF(xxyyyy) ZF(xx)
|
||||||
ZF(xx000A00) ZF(xx0A00) ZF(xxyy0A00) ZF(xxxxyyyy0A00) ZF(xxxx0A00) ZF(xx0A)
|
ZF(xx000A00) ZF(xx0A00) ZF(xxyy0A00) ZF(xxxxyyyy0A00) ZF(xxxx0A00) ZF(xx0A)
|
||||||
ZF(xx190A00) ZF(xx19) ZF(xx190A) ZF(xxxxyyyy) ZF(xxxxyyzz) ZF(xxyyzzzz) ZF(xxyyyyzz)
|
ZF(xx190A00) ZF(xx19) ZF(xx190A) ZF(xxxxyyyy) ZF(xxxxyyzz) ZF(xxyyzzzz) ZF(xxyyyyzz)
|
||||||
|
ZF(01xxxx000000000000) ZF(03xxxx000000000000) ZF(00xxxx000000000000) ZF(xxyyyy000000000000)
|
||||||
ZF(00xx0A00) ZF(01xx0A00) ZF(03xx0A00) ZF(01xxxx0A0000000000) ZF(03xxxx0A0000000000) ZF(xxyyyy0A0000000000)
|
ZF(00xx0A00) ZF(01xx0A00) ZF(03xx0A00) ZF(01xxxx0A0000000000) ZF(03xxxx0A0000000000) ZF(xxyyyy0A0000000000)
|
||||||
|
|
||||||
// Cluster specific commands
|
// Cluster specific commands
|
||||||
|
@ -119,8 +122,12 @@ const Z_CommandConverter Z_Commands[] PROGMEM = {
|
||||||
{ Z(SatStep), 0x0300, 0x05, 0x01, Z(xx190A) },
|
{ Z(SatStep), 0x0300, 0x05, 0x01, Z(xx190A) },
|
||||||
{ Z(ColorMove), 0x0300, 0x08, 0x01, Z(xxxxyyyy) },
|
{ Z(ColorMove), 0x0300, 0x08, 0x01, Z(xxxxyyyy) },
|
||||||
{ Z(ColorStep), 0x0300, 0x09, 0x01, Z(xxxxyyyy0A00) },
|
{ Z(ColorStep), 0x0300, 0x09, 0x01, Z(xxxxyyyy0A00) },
|
||||||
{ Z(ColorTempStepUp), 0x0300, 0x4C, 0x01, Z(01xxxx0A0000000000) }, //xxxx = step
|
{ Z(ColorTempMoveUp), 0x0300, 0x4B, 0x01, Z(01xxxx000000000000) },
|
||||||
{ Z(ColorTempStepDown),0x0300, 0x4C, 0x01, Z(03xxxx0A0000000000) }, //xxxx = step
|
{ Z(ColorTempMoveDown),0x0300, 0x4B, 0x01, Z(03xxxx000000000000) },
|
||||||
|
{ Z(ColorTempMoveStop),0x0300, 0x4B, 0x01, Z(00xxxx000000000000) },
|
||||||
|
{ Z(ColorTempMove), 0x0300, 0x4B, 0x01, Z(xxyyyy000000000000) },
|
||||||
|
{ Z(ColorTempStepUp), 0x0300, 0x4C, 0x01, Z(01xxxx0A0000000000) },
|
||||||
|
{ Z(ColorTempStepDown),0x0300, 0x4C, 0x01, Z(03xxxx0A0000000000) },
|
||||||
{ Z(ColorTempStep), 0x0300, 0x4C, 0x01, Z(xxyyyy0A0000000000) }, //xx = 0x01 up, 0x03 down, yyyy = step
|
{ Z(ColorTempStep), 0x0300, 0x4C, 0x01, Z(xxyyyy0A0000000000) }, //xx = 0x01 up, 0x03 down, yyyy = step
|
||||||
// Tradfri
|
// Tradfri
|
||||||
{ Z(ArrowClick), 0x0005, 0x07, 0x01, Z(xx) }, // xx == 0x01 = left, 0x00 = right
|
{ Z(ArrowClick), 0x0005, 0x07, 0x01, Z(xx) }, // xx == 0x01 = left, 0x00 = right
|
||||||
|
|
|
@ -36,6 +36,8 @@ const uint8_t ZIGBEE_STATUS_DEVICE_INDICATION = 34; // Device announces its
|
||||||
const uint8_t ZIGBEE_STATUS_SCANNING = 40; // State change
|
const uint8_t ZIGBEE_STATUS_SCANNING = 40; // State change
|
||||||
const uint8_t ZIGBEE_STATUS_CC_VERSION = 50; // Status: CC2530 ZNP Version
|
const uint8_t ZIGBEE_STATUS_CC_VERSION = 50; // Status: CC2530 ZNP Version
|
||||||
const uint8_t ZIGBEE_STATUS_CC_INFO = 51; // Status: CC2530 Device Configuration
|
const uint8_t ZIGBEE_STATUS_CC_INFO = 51; // Status: CC2530 Device Configuration
|
||||||
|
const uint8_t ZIGBEE_STATUS_EZ_VERSION = 55; // Status: EFR32 EZ Version
|
||||||
|
const uint8_t ZIGBEE_STATUS_EZ_INFO = 56; // Status: EFR32 EZ Device Configuration
|
||||||
const uint8_t ZIGBEE_STATUS_UNSUPPORTED_VERSION = 98; // Unsupported ZNP version
|
const uint8_t ZIGBEE_STATUS_UNSUPPORTED_VERSION = 98; // Unsupported ZNP version
|
||||||
const uint8_t ZIGBEE_STATUS_ABORT = 99; // Fatal error, Zigbee not working
|
const uint8_t ZIGBEE_STATUS_ABORT = 99; // Fatal error, Zigbee not working
|
||||||
|
|
||||||
|
@ -170,6 +172,19 @@ SBuffer *zigbee_buffer = nullptr;
|
||||||
|
|
||||||
#define USE_ZIGBEE_CHANNEL_MASK (1 << (USE_ZIGBEE_CHANNEL))
|
#define USE_ZIGBEE_CHANNEL_MASK (1 << (USE_ZIGBEE_CHANNEL))
|
||||||
|
|
||||||
|
const char kCheckingDeviceConfiguration[] PROGMEM = D_LOG_ZIGBEE "checking device configuration";
|
||||||
|
const char kConfiguredCoord[] PROGMEM = "Configured, starting coordinator";
|
||||||
|
const char kConfiguredRouter[] PROGMEM = "Configured, starting router";
|
||||||
|
const char kConfiguredDevice[] PROGMEM = "Configured, starting device";
|
||||||
|
const char kStarted[] PROGMEM = "Started";
|
||||||
|
const char kZigbeeStarted[] PROGMEM = D_LOG_ZIGBEE "Zigbee started";
|
||||||
|
const char kResetting[] PROGMEM = "Resetting configuration";
|
||||||
|
const char kResettingDevice[] PROGMEM = D_LOG_ZIGBEE "Resetting EZSP device";
|
||||||
|
const char kZNP12[] PROGMEM = "Only ZNP 1.2 is currently supported";
|
||||||
|
const char kEZ8[] PROGMEM = "Only EZSP protocol v8 is currently supported";
|
||||||
|
const char kAbort[] PROGMEM = "Abort";
|
||||||
|
const char kZigbeeAbort[] PROGMEM = D_LOG_ZIGBEE "Abort";
|
||||||
|
|
||||||
#ifdef USE_ZIGBEE_ZNP
|
#ifdef USE_ZIGBEE_ZNP
|
||||||
|
|
||||||
// ZBS_* Zigbee Send
|
// ZBS_* Zigbee Send
|
||||||
|
@ -402,17 +417,6 @@ void Z_UpdateConfig(uint8_t zb_channel, uint16_t zb_pan_id, uint64_t zb_ext_pani
|
||||||
) // 2605621001030507090B0D0F00020406080A0C0D
|
) // 2605621001030507090B0D0F00020406080A0C0D
|
||||||
}
|
}
|
||||||
|
|
||||||
const char kCheckingDeviceConfiguration[] PROGMEM = D_LOG_ZIGBEE "checking device configuration";
|
|
||||||
const char kConfiguredCoord[] PROGMEM = "Configured, starting coordinator";
|
|
||||||
const char kConfiguredRouter[] PROGMEM = "Configured, starting router";
|
|
||||||
const char kConfiguredDevice[] PROGMEM = "Configured, starting device";
|
|
||||||
const char kStarted[] PROGMEM = "Started";
|
|
||||||
const char kZigbeeStarted[] PROGMEM = D_LOG_ZIGBEE "Zigbee started";
|
|
||||||
const char kResetting[] PROGMEM = "Resetting configuration";
|
|
||||||
const char kZNP12[] PROGMEM = "Only ZNP 1.2 is currently supported";
|
|
||||||
const char kAbort[] PROGMEM = "Abort";
|
|
||||||
const char kZigbeeAbort[] PROGMEM = D_LOG_ZIGBEE "Abort";
|
|
||||||
|
|
||||||
static const Zigbee_Instruction zb_prog[] PROGMEM = {
|
static const Zigbee_Instruction zb_prog[] PROGMEM = {
|
||||||
ZI_LABEL(0)
|
ZI_LABEL(0)
|
||||||
ZI_NOOP()
|
ZI_NOOP()
|
||||||
|
@ -654,8 +658,7 @@ ZBM(ZBS_SET_TC_CACHE, EZSP_setConfigurationValue, 0x00 /*high*/, EZSP_CONFIG
|
||||||
ZBM(ZBS_SET_ROUTE_TBL, EZSP_setConfigurationValue, 0x00 /*high*/, EZSP_CONFIG_SOURCE_ROUTE_TABLE_SIZE, 0x10, 0x00) // 53001A1000
|
ZBM(ZBS_SET_ROUTE_TBL, EZSP_setConfigurationValue, 0x00 /*high*/, EZSP_CONFIG_SOURCE_ROUTE_TABLE_SIZE, 0x10, 0x00) // 53001A1000
|
||||||
ZBM(ZBS_SET_KEY_TBL, EZSP_setConfigurationValue, 0x00 /*high*/, EZSP_CONFIG_KEY_TABLE_SIZE, 0x04, 0x00) // 53001E0400
|
ZBM(ZBS_SET_KEY_TBL, EZSP_setConfigurationValue, 0x00 /*high*/, EZSP_CONFIG_KEY_TABLE_SIZE, 0x04, 0x00) // 53001E0400
|
||||||
ZBM(ZBS_SET_PANID_CNFLCT, EZSP_setConfigurationValue, 0x00 /*high*/, EZSP_CONFIG_PAN_ID_CONFLICT_REPORT_THRESHOLD, 0x02, 0x00)// 5300220200
|
ZBM(ZBS_SET_PANID_CNFLCT, EZSP_setConfigurationValue, 0x00 /*high*/, EZSP_CONFIG_PAN_ID_CONFLICT_REPORT_THRESHOLD, 0x02, 0x00)// 5300220200
|
||||||
// TODO APP_RECEIVES_SUPPORTED_ZDO_REQUESTS
|
ZBM(ZBS_SET_ZDO_REQ, EZSP_setConfigurationValue, 0x00 /*high*/, EZSP_CONFIG_APPLICATION_ZDO_FLAGS, EMBER_APP_RECEIVES_SUPPORTED_ZDO_REQUESTS | EMBER_APP_HANDLES_UNSUPPORTED_ZDO_REQUESTS, 0x00) // 53002A0300
|
||||||
ZBM(ZBS_SET_ZDO_REQ, EZSP_setConfigurationValue, 0x00 /*high*/, EZSP_CONFIG_APPLICATION_ZDO_FLAGS, 0x03, 0x00) // 53002A0300
|
|
||||||
ZBM(ZBS_SET_NETWORKS, EZSP_setConfigurationValue, 0x00 /*high*/, EZSP_CONFIG_SUPPORTED_NETWORKS, 0x01, 0x00) // 53002D0100
|
ZBM(ZBS_SET_NETWORKS, EZSP_setConfigurationValue, 0x00 /*high*/, EZSP_CONFIG_SUPPORTED_NETWORKS, 0x01, 0x00) // 53002D0100
|
||||||
ZBM(ZBS_SET_PACKET_BUF, EZSP_setConfigurationValue, 0x00 /*high*/, EZSP_CONFIG_PACKET_BUFFER_COUNT, 0xFF, 0x00) // 530001FF00
|
ZBM(ZBS_SET_PACKET_BUF, EZSP_setConfigurationValue, 0x00 /*high*/, EZSP_CONFIG_PACKET_BUFFER_COUNT, 0xFF, 0x00) // 530001FF00
|
||||||
|
|
||||||
|
@ -667,23 +670,24 @@ ZBM(ZBS_GET_APS_UNI, EZSP_getConfigurationValue, 0x00 /*high*/, EZSP_CONFIG
|
||||||
ZBM(ZBR_GET_OK, EZSP_getConfigurationValue, 0x00 /*high*/, 0x00 /*ok*/) // 5200 - followed by the value
|
ZBM(ZBR_GET_OK, EZSP_getConfigurationValue, 0x00 /*high*/, 0x00 /*ok*/) // 5200 - followed by the value
|
||||||
|
|
||||||
// Add Endpoints
|
// Add Endpoints
|
||||||
// ZBM(ZBS_ADD_ENDPOINT1, EZSP_addEndpoint, 0x00 /*high*/, 0x01 /*ep*/, Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA),
|
|
||||||
// 0x05, 0x00 /* AppDeviceId */, 0x00 /* AppDevVer */,
|
|
||||||
// 0x0E /* inputClusterCount */, // actually all clusters will be received
|
|
||||||
// 0X00 /* outputClusterCount */,
|
|
||||||
// 0x00,0x00, 0x04,0x00, 0x05,0x00, 0x06,0x00, // 0x0000, 0x0004, 0x0005, 0x0006
|
|
||||||
// 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
|
|
||||||
// )
|
|
||||||
ZBM(ZBS_ADD_ENDPOINT1, EZSP_addEndpoint, 0x00 /*high*/, 0x01 /*ep*/, Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA),
|
ZBM(ZBS_ADD_ENDPOINT1, EZSP_addEndpoint, 0x00 /*high*/, 0x01 /*ep*/, Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA),
|
||||||
0x05, 0x00 /* AppDeviceId */, 0x00 /* AppDevVer */,
|
0x05, 0x00 /* AppDeviceId */, 0x00 /* AppDevVer */,
|
||||||
0x00 /* inputClusterCount */, // actually all clusters will be received
|
0x0E /* inputClusterCount */, // actually all clusters will be received
|
||||||
0X00 /* outputClusterCount */ ) // 02000104010500000000
|
0X00 /* outputClusterCount */, // 02000104010500000000
|
||||||
|
0x00,0x00, 0x04,0x00, 0x05,0x00, 0x06,0x00, // 0x0000, 0x0004, 0x0005, 0x0006
|
||||||
|
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
|
||||||
|
)
|
||||||
ZBM(ZBS_ADD_ENDPOINTB, EZSP_addEndpoint, 0x00 /*high*/, 0x0B /*ep*/, Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA),
|
ZBM(ZBS_ADD_ENDPOINTB, EZSP_addEndpoint, 0x00 /*high*/, 0x0B /*ep*/, Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA),
|
||||||
0x05, 0x00 /* AppDeviceId */, 0x00 /* AppDevVer */,
|
0x05, 0x00 /* AppDeviceId */, 0x00 /* AppDevVer */,
|
||||||
0x00 /* inputClusterCount */, // actually all clusters will be received
|
0x0E /* inputClusterCount */, // actually all clusters will be received
|
||||||
0X00 /* outputClusterCount */ ) // 02000B04010500000000
|
0X00 /* outputClusterCount */, // 02000B04010500000000
|
||||||
|
0x00,0x00, 0x04,0x00, 0x05,0x00, 0x06,0x00, // 0x0000, 0x0004, 0x0005, 0x0006
|
||||||
|
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
|
||||||
|
)
|
||||||
ZBM(ZBR_ADD_ENDPOINT, EZSP_addEndpoint, 0x00 /*high*/, 0x00 /*ok*/) // 020000
|
ZBM(ZBR_ADD_ENDPOINT, EZSP_addEndpoint, 0x00 /*high*/, 0x00 /*ok*/) // 020000
|
||||||
|
|
||||||
// set concentrator false
|
// set concentrator false
|
||||||
|
@ -691,11 +695,58 @@ ZBM(ZBS_SET_CONCENTRATOR, EZSP_setConcentrator, 0x00 /*high*/, 0x00 /*false*/, 0
|
||||||
0x58,0x02 /*minTime*/, 0x08,0x07 /*maxTime*/, 0x02 /*errThr*/, 0x05 /*failThr*/, 0x00 /*maxHops*/) // 100000F9FF58020807020500
|
0x58,0x02 /*minTime*/, 0x08,0x07 /*maxTime*/, 0x02 /*errThr*/, 0x05 /*failThr*/, 0x00 /*maxHops*/) // 100000F9FF58020807020500
|
||||||
ZBM(ZBR_SET_CONCENTRATOR, EZSP_setConcentrator, 0x00 /*high*/, 0x00 /*ok*/) // 100000
|
ZBM(ZBR_SET_CONCENTRATOR, EZSP_setConcentrator, 0x00 /*high*/, 0x00 /*ok*/) // 100000
|
||||||
|
|
||||||
//False, <EmberConcentratorType.HIGH_RAM_CONCENTRATOR: 65529>, 600, 1800, 2, 5, 0)
|
// setInitialSecurityState
|
||||||
|
#define EZ_SECURITY_MODE EMBER_TRUST_CENTER_GLOBAL_LINK_KEY | EMBER_PRECONFIGURED_NETWORK_KEY_MODE | EMBER_HAVE_NETWORK_KEY | EMBER_HAVE_PRECONFIGURED_KEY
|
||||||
|
ZBM(ZBS_SET_SECURITY, EZSP_setInitialSecurityState, 0x00 /*high*/,
|
||||||
|
Z_B0(EZ_SECURITY_MODE), Z_B1(EZ_SECURITY_MODE),
|
||||||
|
// preConfiguredKey
|
||||||
|
0x5A, 0x69, 0x67, 0x42, 0x65, 0x65, 0x41, 0x6C, 0x6C, 0x69, 0x61, 0x6E, 0x63, 0x65, 0x30, 0x39, // well known key "ZigBeeAlliance09"
|
||||||
|
// networkKey
|
||||||
|
Z_B0(USE_ZIGBEE_PRECFGKEY_L), Z_B1(USE_ZIGBEE_PRECFGKEY_L), Z_B2(USE_ZIGBEE_PRECFGKEY_L), Z_B3(USE_ZIGBEE_PRECFGKEY_L),
|
||||||
|
Z_B4(USE_ZIGBEE_PRECFGKEY_L), Z_B5(USE_ZIGBEE_PRECFGKEY_L), Z_B6(USE_ZIGBEE_PRECFGKEY_L), Z_B7(USE_ZIGBEE_PRECFGKEY_L),
|
||||||
|
Z_B0(USE_ZIGBEE_PRECFGKEY_H), Z_B1(USE_ZIGBEE_PRECFGKEY_H), Z_B2(USE_ZIGBEE_PRECFGKEY_H), Z_B3(USE_ZIGBEE_PRECFGKEY_H),
|
||||||
|
Z_B4(USE_ZIGBEE_PRECFGKEY_H), Z_B5(USE_ZIGBEE_PRECFGKEY_H), Z_B6(USE_ZIGBEE_PRECFGKEY_H), Z_B7(USE_ZIGBEE_PRECFGKEY_H),
|
||||||
|
0x00 /*sequence*/,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*trustcenter*/
|
||||||
|
)
|
||||||
|
ZBM(ZBR_SET_SECURITY, EZSP_setInitialSecurityState, 0x00 /*high*/, 0x00 /*status*/)
|
||||||
|
|
||||||
|
// setIndividual policies
|
||||||
|
ZBM(ZBS_SET_POLICY_00, EZSP_setPolicy, 0x00 /*high*/, EZSP_TRUST_CENTER_POLICY,
|
||||||
|
EZSP_DECISION_ALLOW_JOINS | EZSP_DECISION_ALLOW_UNSECURED_REJOINS) // 55000003
|
||||||
|
ZBM(ZBS_SET_POLICY_02, EZSP_setPolicy, 0x00 /*high*/, EZSP_UNICAST_REPLIES_POLICY,
|
||||||
|
EZSP_HOST_WILL_NOT_SUPPLY_REPLY) // 550002210
|
||||||
|
ZBM(ZBS_SET_POLICY_03, EZSP_setPolicy, 0x00 /*high*/, EZSP_POLL_HANDLER_POLICY,
|
||||||
|
EZSP_POLL_HANDLER_IGNORE) // 55000330
|
||||||
|
ZBM(ZBS_SET_POLICY_05, EZSP_setPolicy, 0x00 /*high*/, EZSP_TC_KEY_REQUEST_POLICY,
|
||||||
|
EZSP_ALLOW_TC_KEY_REQUESTS_AND_SEND_CURRENT_KEY) // 55000551
|
||||||
|
ZBM(ZBS_SET_POLICY_06, EZSP_setPolicy, 0x00 /*high*/, EZSP_APP_KEY_REQUEST_POLICY,
|
||||||
|
EZSP_DENY_APP_KEY_REQUESTS) // 55000660
|
||||||
|
ZBM(ZBR_SET_POLICY_XX, EZSP_setPolicy, 0x00 /*high*/, 0x00 /*status*/)
|
||||||
|
|
||||||
|
// formNetwork - i.e. start zigbee network as coordinator
|
||||||
|
ZBM(ZBS_FORM_NETWORK, EZSP_formNetwork, 0x00 /*high*/,
|
||||||
|
Z_B0(USE_ZIGBEE_EXTPANID), Z_B1(USE_ZIGBEE_EXTPANID), Z_B2(USE_ZIGBEE_EXTPANID), Z_B3(USE_ZIGBEE_EXTPANID),
|
||||||
|
Z_B4(USE_ZIGBEE_EXTPANID), Z_B5(USE_ZIGBEE_EXTPANID), Z_B6(USE_ZIGBEE_EXTPANID), Z_B7(USE_ZIGBEE_EXTPANID),
|
||||||
|
Z_B0(USE_ZIGBEE_PANID), Z_B1(USE_ZIGBEE_PANID),
|
||||||
|
20 /*radioTxPower*/,
|
||||||
|
USE_ZIGBEE_CHANNEL /*channel*/,
|
||||||
|
EMBER_USE_MAC_ASSOCIATION,
|
||||||
|
0xFF,0xFF, /*nwkManagerId, unused*/
|
||||||
|
0x00, /*nwkUpdateId, unused*/
|
||||||
|
0x00,0x00,0x00,0x00, /*NWK channel mask, unused*/
|
||||||
|
) // 1E00...
|
||||||
|
ZBM(ZBR_FORM_NETWORK, EZSP_formNetwork, 0x00 /*high*/, 0x00 /*status*/) // 1E0000
|
||||||
|
ZBM(ZBR_NETWORK_UP, EZSP_stackStatusHandler, 0x00 /*high*/, EMBER_NETWORK_UP) // 190090
|
||||||
|
|
||||||
|
// read configuration details
|
||||||
|
ZBM(ZBS_GET_NETW_PARM, EZSP_getNetworkParameters, 0x00 /*high*/) // 2800
|
||||||
|
ZBM(ZBR_GET_NETW_PARM, EZSP_getNetworkParameters, 0x00 /*high*/, 0x00 /*ok*/) // 2800
|
||||||
|
ZBM(ZBS_GET_EUI64, EZSP_getEui64, 0x00 /*high*/) // 2600
|
||||||
|
ZBM(ZBR_GET_EUI64, EZSP_getEui64, 0x00 /*high*/) // 2600
|
||||||
|
ZBM(ZBS_GET_NODEID, EZSP_getNodeId, 0x00 /*high*/) // 2700
|
||||||
|
ZBM(ZBR_GET_NODEID, EZSP_getNodeId, 0x00 /*high*/) // 2700
|
||||||
|
|
||||||
const char kResetingDevice[] PROGMEM = D_LOG_ZIGBEE "resetting EZSP device";
|
|
||||||
const char kAbort[] PROGMEM = "Abort";
|
|
||||||
const char kZigbeeAbort[] PROGMEM = D_LOG_ZIGBEE "Abort";
|
|
||||||
|
|
||||||
static const Zigbee_Instruction zb_prog[] PROGMEM = {
|
static const Zigbee_Instruction zb_prog[] PROGMEM = {
|
||||||
ZI_LABEL(0)
|
ZI_LABEL(0)
|
||||||
|
@ -706,7 +757,7 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
|
||||||
ZI_WAIT(10500) // wait for 10 seconds for Tasmota to stabilize
|
ZI_WAIT(10500) // wait for 10 seconds for Tasmota to stabilize
|
||||||
|
|
||||||
// Hardware reset
|
// Hardware reset
|
||||||
ZI_LOG(LOG_LEVEL_INFO, kResetingDevice) // Log Debug: resetting EZSP device
|
ZI_LOG(LOG_LEVEL_INFO, kResettingDevice) // Log Debug: resetting EZSP device
|
||||||
ZI_CALL(&Z_Reset_Device, 0) // LOW = reset
|
ZI_CALL(&Z_Reset_Device, 0) // LOW = reset
|
||||||
ZI_WAIT(100) // wait for .1 second
|
ZI_WAIT(100) // wait for .1 second
|
||||||
ZI_CALL(&Z_Reset_Device, 1) // HIGH = release reset
|
ZI_CALL(&Z_Reset_Device, 1) // HIGH = release reset
|
||||||
|
@ -715,9 +766,10 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
|
||||||
ZI_WAIT_UNTIL(5000, ZBR_RSTACK) // wait for RSTACK message
|
ZI_WAIT_UNTIL(5000, ZBR_RSTACK) // wait for RSTACK message
|
||||||
|
|
||||||
// Init device and probe version
|
// Init device and probe version
|
||||||
ZI_SEND(ZBS_VERSION) ZI_WAIT_RECV(1000, ZBR_VERSION) // check EXT PAN ID
|
ZI_SEND(ZBS_VERSION) ZI_WAIT_RECV_FUNC(1000, ZBR_VERSION, &Z_ReceiveCheckVersion) // check EXT PAN ID
|
||||||
|
|
||||||
// configure EFR32
|
// configure EFR32
|
||||||
|
ZI_MQTT_STATE(ZIGBEE_STATUS_STARTING, kConfiguredCoord)
|
||||||
ZI_SEND(ZBS_SET_ADDR_TABLE) ZI_WAIT_RECV(500, ZBR_SET_OK) // Address table size
|
ZI_SEND(ZBS_SET_ADDR_TABLE) ZI_WAIT_RECV(500, ZBR_SET_OK) // Address table size
|
||||||
ZI_SEND(ZBS_SET_MCAST_TABLE) ZI_WAIT_RECV(500, ZBR_SET_OK)
|
ZI_SEND(ZBS_SET_MCAST_TABLE) ZI_WAIT_RECV(500, ZBR_SET_OK)
|
||||||
ZI_SEND(ZBS_SET_STK_PROF) ZI_WAIT_RECV(500, ZBR_SET_OK)
|
ZI_SEND(ZBS_SET_STK_PROF) ZI_WAIT_RECV(500, ZBR_SET_OK)
|
||||||
|
@ -733,7 +785,8 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
|
||||||
ZI_SEND(ZBS_SET_PACKET_BUF) ZI_WAIT_RECV(500, ZBR_SET_OK2)
|
ZI_SEND(ZBS_SET_PACKET_BUF) ZI_WAIT_RECV(500, ZBR_SET_OK2)
|
||||||
|
|
||||||
// read configuration
|
// read configuration
|
||||||
ZI_SEND(ZBS_GET_APS_UNI) ZI_WAIT_RECV_FUNC(500, ZBR_GET_OK, &Z_ReadAPSUnicastMessage)
|
// TODO - not sure it's useful
|
||||||
|
//ZI_SEND(ZBS_GET_APS_UNI) ZI_WAIT_RECV_FUNC(500, ZBR_GET_OK, &Z_ReadAPSUnicastMessage)
|
||||||
|
|
||||||
// add endpoint 0x01 and 0x0B
|
// add endpoint 0x01 and 0x0B
|
||||||
ZI_SEND(ZBS_ADD_ENDPOINT1) ZI_WAIT_RECV(500, ZBR_ADD_ENDPOINT)
|
ZI_SEND(ZBS_ADD_ENDPOINT1) ZI_WAIT_RECV(500, ZBR_ADD_ENDPOINT)
|
||||||
|
@ -742,9 +795,38 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
|
||||||
// set Concentrator
|
// set Concentrator
|
||||||
ZI_SEND(ZBS_SET_CONCENTRATOR) ZI_WAIT_RECV(500, ZBR_SET_CONCENTRATOR)
|
ZI_SEND(ZBS_SET_CONCENTRATOR) ZI_WAIT_RECV(500, ZBR_SET_CONCENTRATOR)
|
||||||
|
|
||||||
|
// setInitialSecurityState
|
||||||
|
ZI_SEND(ZBS_SET_SECURITY) ZI_WAIT_RECV(500, ZBR_SET_SECURITY)
|
||||||
|
ZI_SEND(ZBS_SET_POLICY_00) ZI_WAIT_RECV(500, ZBR_SET_POLICY_XX)
|
||||||
|
ZI_SEND(ZBS_SET_POLICY_02) ZI_WAIT_RECV(500, ZBR_SET_POLICY_XX)
|
||||||
|
ZI_SEND(ZBS_SET_POLICY_03) ZI_WAIT_RECV(500, ZBR_SET_POLICY_XX)
|
||||||
|
ZI_SEND(ZBS_SET_POLICY_05) ZI_WAIT_RECV(500, ZBR_SET_POLICY_XX)
|
||||||
|
ZI_SEND(ZBS_SET_POLICY_06) ZI_WAIT_RECV(500, ZBR_SET_POLICY_XX)
|
||||||
|
|
||||||
|
// formNetwork
|
||||||
|
ZI_SEND(ZBS_FORM_NETWORK) ZI_WAIT_RECV(500, ZBR_FORM_NETWORK)
|
||||||
|
ZI_WAIT_RECV(5000, ZBR_NETWORK_UP) // wait for network to start
|
||||||
|
|
||||||
|
// Query device information
|
||||||
|
ZI_SEND(ZBS_GET_EUI64) ZI_WAIT_RECV_FUNC(500, ZBR_GET_EUI64, &Z_EZSPGetEUI64)
|
||||||
|
ZI_SEND(ZBS_GET_NODEID) ZI_WAIT_RECV_FUNC(500, ZBR_GET_NODEID, &Z_EZSPGetNodeId)
|
||||||
|
ZI_SEND(ZBS_GET_NETW_PARM) ZI_WAIT_RECV_FUNC(500, ZBR_GET_NETW_PARM, &Z_EZSPNetworkParameters)
|
||||||
|
|
||||||
|
ZI_LABEL(ZIGBEE_LABEL_READY)
|
||||||
|
ZI_MQTT_STATE(ZIGBEE_STATUS_OK, kStarted)
|
||||||
|
ZI_LOG(LOG_LEVEL_INFO, kZigbeeStarted)
|
||||||
|
ZI_CALL(&Z_State_Ready, 1) // Now accept incoming messages
|
||||||
|
ZI_CALL(&Z_Load_Devices, 0)
|
||||||
|
ZI_CALL(&Z_Query_Bulbs, 0)
|
||||||
|
|
||||||
ZI_LABEL(ZIGBEE_LABEL_MAIN_LOOP)
|
ZI_LABEL(ZIGBEE_LABEL_MAIN_LOOP)
|
||||||
ZI_WAIT_FOREVER()
|
ZI_WAIT_FOREVER()
|
||||||
ZI_GOTO(ZIGBEE_LABEL_READY)
|
ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP)
|
||||||
|
|
||||||
|
// Error: version of Z-Stack is not supported
|
||||||
|
ZI_LABEL(ZIGBEE_LABEL_UNSUPPORTED_VERSION)
|
||||||
|
ZI_MQTT_STATE(ZIGBEE_STATUS_UNSUPPORTED_VERSION, kEZ8)
|
||||||
|
ZI_GOTO(ZIGBEE_LABEL_ABORT)
|
||||||
|
|
||||||
// Abort state machine, general error
|
// Abort state machine, general error
|
||||||
ZI_LABEL(ZIGBEE_LABEL_ABORT) // Label 99: abort
|
ZI_LABEL(ZIGBEE_LABEL_ABORT) // Label 99: abort
|
||||||
|
|
|
@ -64,26 +64,6 @@ int32_t Z_EZSP_ERROR(uint8_t error_code) {
|
||||||
XdrvRulesProcess();
|
XdrvRulesProcess();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************************************\
|
|
||||||
* Default resolver
|
|
||||||
\*********************************************************************************************/
|
|
||||||
|
|
||||||
int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf) {
|
|
||||||
// Default message handler for new messages
|
|
||||||
if (zigbee.init_phase) {
|
|
||||||
// if still during initialization phase, ignore any unexpected message
|
|
||||||
return -1; // ignore message
|
|
||||||
} else {
|
|
||||||
// TODO
|
|
||||||
// for (uint32_t i = 0; i < sizeof(Z_DispatchTable)/sizeof(Z_Dispatcher); i++) {
|
|
||||||
// if (Z_ReceiveMatchPrefix(buf, Z_DispatchTable[i].match)) {
|
|
||||||
// (*Z_DispatchTable[i].func)(res, buf);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t Z_ReadAPSUnicastMessage(int32_t res, class SBuffer &buf) {
|
int32_t Z_ReadAPSUnicastMessage(int32_t res, class SBuffer &buf) {
|
||||||
// Called when receiving a response from getConfigurationValue
|
// Called when receiving a response from getConfigurationValue
|
||||||
// Value is in bytes 2+3
|
// Value is in bytes 2+3
|
||||||
|
@ -94,6 +74,53 @@ int32_t Z_ReadAPSUnicastMessage(int32_t res, class SBuffer &buf) {
|
||||||
|
|
||||||
#endif // USE_ZIGBEE_EZSP
|
#endif // USE_ZIGBEE_EZSP
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Parsers for incoming EZSP messages
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
//
|
||||||
|
// Handle a "getEui64" incoming message
|
||||||
|
//
|
||||||
|
int32_t Z_EZSPGetEUI64(int32_t res, class SBuffer &buf) {
|
||||||
|
localIEEEAddr = buf.get64(2);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Handle a "getEui64" incoming message
|
||||||
|
//
|
||||||
|
int32_t Z_EZSPGetNodeId(int32_t res, class SBuffer &buf) {
|
||||||
|
localShortAddr = buf.get8(2);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Handle a "getNetworkParameters" incoming message
|
||||||
|
//
|
||||||
|
int32_t Z_EZSPNetworkParameters(int32_t res, class SBuffer &buf) {
|
||||||
|
uint8_t node_type = buf.get8(3);
|
||||||
|
// ext panid: 4->11
|
||||||
|
// panid: 12->13
|
||||||
|
// radioTxPower: 14
|
||||||
|
// radioChannel: 15
|
||||||
|
|
||||||
|
// Local short and long addresses are supposed to be already retrieved
|
||||||
|
// localIEEEAddr = long_adr;
|
||||||
|
// localShortAddr = short_adr;
|
||||||
|
|
||||||
|
char hex[20];
|
||||||
|
Uint64toHex(localIEEEAddr, hex, 64);
|
||||||
|
Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{"
|
||||||
|
"\"Status\":%d,\"IEEEAddr\":\"0x%s\",\"ShortAddr\":\"0x%04X\""
|
||||||
|
",\"DeviceType\":%d}}"),
|
||||||
|
ZIGBEE_STATUS_EZ_INFO, hex, localShortAddr, node_type);
|
||||||
|
|
||||||
|
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE));
|
||||||
|
XdrvRulesProcess();
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Parsers for incoming ZNP messages
|
* Parsers for incoming ZNP messages
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
@ -117,6 +144,7 @@ int32_t Z_ReceiveDeviceInfo(int32_t res, class SBuffer &buf) {
|
||||||
|
|
||||||
// keep track of the local IEEE address
|
// keep track of the local IEEE address
|
||||||
localIEEEAddr = long_adr;
|
localIEEEAddr = long_adr;
|
||||||
|
localShortAddr = short_adr;
|
||||||
|
|
||||||
char hex[20];
|
char hex[20];
|
||||||
Uint64toHex(long_adr, hex, 64);
|
Uint64toHex(long_adr, hex, 64);
|
||||||
|
@ -194,6 +222,7 @@ int32_t Z_Reboot(int32_t res, class SBuffer &buf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t Z_ReceiveCheckVersion(int32_t res, class SBuffer &buf) {
|
int32_t Z_ReceiveCheckVersion(int32_t res, class SBuffer &buf) {
|
||||||
|
#ifdef USE_ZIGBEE_ZNP
|
||||||
// check that the version is supported
|
// check that the version is supported
|
||||||
// typical version for ZNP 1.2
|
// typical version for ZNP 1.2
|
||||||
// 61020200-02.06.03.D9143401.0200000000
|
// 61020200-02.06.03.D9143401.0200000000
|
||||||
|
@ -222,6 +251,34 @@ int32_t Z_ReceiveCheckVersion(int32_t res, class SBuffer &buf) {
|
||||||
} else {
|
} else {
|
||||||
return ZIGBEE_LABEL_UNSUPPORTED_VERSION; // abort
|
return ZIGBEE_LABEL_UNSUPPORTED_VERSION; // abort
|
||||||
}
|
}
|
||||||
|
#endif // USE_ZIGBEE_ZNP
|
||||||
|
|
||||||
|
#ifdef USE_ZIGBEE_EZSP
|
||||||
|
uint8_t protocol_version = buf.get8(2);
|
||||||
|
uint8_t stack_type = buf.get8(3);
|
||||||
|
uint16_t stack_version = buf.get16(4);
|
||||||
|
|
||||||
|
Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{"
|
||||||
|
"\"Status\":%d,\"Version\":\"%d.%d.%d.%d\",\"Protocol\":%d"
|
||||||
|
",\"Stack\":%d}}"),
|
||||||
|
ZIGBEE_STATUS_EZ_VERSION,
|
||||||
|
(stack_version & 0xF000) >> 12,
|
||||||
|
(stack_version & 0x0F00) >> 8,
|
||||||
|
(stack_version & 0x00F0) >> 4,
|
||||||
|
stack_version & 0x000F,
|
||||||
|
protocol_version,
|
||||||
|
stack_type
|
||||||
|
);
|
||||||
|
|
||||||
|
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE));
|
||||||
|
XdrvRulesProcess();
|
||||||
|
|
||||||
|
if (0x08 == protocol_version) {
|
||||||
|
return 0; // protocol v8 is ok
|
||||||
|
} else {
|
||||||
|
return ZIGBEE_LABEL_UNSUPPORTED_VERSION; // abort
|
||||||
|
}
|
||||||
|
#endif // USE_ZIGBEE_EZSP
|
||||||
}
|
}
|
||||||
|
|
||||||
// checks the device type (coordinator, router, end-device)
|
// checks the device type (coordinator, router, end-device)
|
||||||
|
@ -466,10 +523,18 @@ int32_t Z_ReceiveStateChange(int32_t res, const class SBuffer &buf) {
|
||||||
// Send back Active Ep Req message
|
// Send back Active Ep Req message
|
||||||
//
|
//
|
||||||
int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) {
|
int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) {
|
||||||
Z_ShortAddress srcAddr = buf.get16(2);
|
#ifdef USE_ZIGBEE_ZNP
|
||||||
|
// Z_ShortAddress srcAddr = buf.get16(2);
|
||||||
Z_ShortAddress nwkAddr = buf.get16(4);
|
Z_ShortAddress nwkAddr = buf.get16(4);
|
||||||
Z_IEEEAddress ieeeAddr = buf.get64(6);
|
Z_IEEEAddress ieeeAddr = buf.get64(6);
|
||||||
uint8_t capabilities = buf.get8(14);
|
uint8_t capabilities = buf.get8(14);
|
||||||
|
#endif
|
||||||
|
#ifdef USE_ZIGBEE_EZSP
|
||||||
|
// uint8_t seq = buf.get8(0);
|
||||||
|
Z_ShortAddress nwkAddr = buf.get16(1);
|
||||||
|
Z_IEEEAddress ieeeAddr = buf.get64(3);
|
||||||
|
uint8_t capabilities = buf.get8(11);
|
||||||
|
#endif
|
||||||
|
|
||||||
zigbee_devices.updateDevice(nwkAddr, ieeeAddr);
|
zigbee_devices.updateDevice(nwkAddr, ieeeAddr);
|
||||||
|
|
||||||
|
@ -627,7 +692,6 @@ int32_t Z_MgmtBindRsp(int32_t res, const class SBuffer &buf) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_ZIGBEE_ZNP
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Send specific ZNP messages
|
* Send specific ZNP messages
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
@ -636,24 +700,32 @@ int32_t Z_MgmtBindRsp(int32_t res, const class SBuffer &buf) {
|
||||||
// Send ZDO_IEEE_ADDR_REQ request to get IEEE long address
|
// Send ZDO_IEEE_ADDR_REQ request to get IEEE long address
|
||||||
//
|
//
|
||||||
void Z_SendIEEEAddrReq(uint16_t shortaddr) {
|
void Z_SendIEEEAddrReq(uint16_t shortaddr) {
|
||||||
|
#ifdef USE_ZIGBEE_ZNP
|
||||||
uint8_t IEEEAddrReq[] = { Z_SREQ | Z_ZDO, ZDO_IEEE_ADDR_REQ, Z_B0(shortaddr), Z_B1(shortaddr), 0x00, 0x00 };
|
uint8_t IEEEAddrReq[] = { Z_SREQ | Z_ZDO, ZDO_IEEE_ADDR_REQ, Z_B0(shortaddr), Z_B1(shortaddr), 0x00, 0x00 };
|
||||||
|
|
||||||
ZigbeeZNPSend(IEEEAddrReq, sizeof(IEEEAddrReq));
|
ZigbeeZNPSend(IEEEAddrReq, sizeof(IEEEAddrReq));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Send ACTIVE_EP_REQ to collect active endpoints for this address
|
// Send ACTIVE_EP_REQ to collect active endpoints for this address
|
||||||
//
|
//
|
||||||
void Z_SendActiveEpReq(uint16_t shortaddr) {
|
void Z_SendActiveEpReq(uint16_t shortaddr) {
|
||||||
|
#ifdef USE_ZIGBEE_ZNP
|
||||||
uint8_t ActiveEpReq[] = { Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) };
|
uint8_t ActiveEpReq[] = { Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) };
|
||||||
|
|
||||||
ZigbeeZNPSend(ActiveEpReq, sizeof(ActiveEpReq));
|
ZigbeeZNPSend(ActiveEpReq, sizeof(ActiveEpReq));
|
||||||
|
#endif
|
||||||
|
#ifdef USE_ZIGBEE_EZSP
|
||||||
|
uint8_t ActiveEpReq[] = { Z_B0(shortaddr), Z_B1(shortaddr) };
|
||||||
|
EZ_SendZDO(shortaddr, ZDO_Active_EP_req, ActiveEpReq, sizeof(ActiveEpReq));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Send AF Info Request
|
// Send AF Info Request
|
||||||
//
|
//
|
||||||
void Z_SendAFInfoRequest(uint16_t shortaddr) {
|
void Z_SendAFInfoRequest(uint16_t shortaddr) {
|
||||||
|
#ifdef USE_ZIGBEE_ZNP
|
||||||
uint8_t endpoint = zigbee_devices.findFirstEndpoint(shortaddr);
|
uint8_t endpoint = zigbee_devices.findFirstEndpoint(shortaddr);
|
||||||
if (0x00 == endpoint) { endpoint = 0x01; } // if we don't know the endpoint, try 0x01
|
if (0x00 == endpoint) { endpoint = 0x01; } // if we don't know the endpoint, try 0x01
|
||||||
uint8_t transacid = zigbee_devices.getNextSeqNumber(shortaddr);
|
uint8_t transacid = zigbee_devices.getNextSeqNumber(shortaddr);
|
||||||
|
@ -663,102 +735,59 @@ void Z_SendAFInfoRequest(uint16_t shortaddr) {
|
||||||
0x00, transacid, ZCL_READ_ATTRIBUTES, 0x04, 0x00, 0x05, 0x00
|
0x00, transacid, ZCL_READ_ATTRIBUTES, 0x04, 0x00, 0x05, 0x00
|
||||||
};
|
};
|
||||||
ZigbeeZNPSend(AFInfoReq, sizeof(AFInfoReq));
|
ZigbeeZNPSend(AFInfoReq, sizeof(AFInfoReq));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // USE_ZIGBEE_ZNP
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Handle trustCenterJoinHandler
|
||||||
|
// 2400
|
||||||
|
//
|
||||||
#ifdef USE_ZIGBEE_EZSP
|
#ifdef USE_ZIGBEE_EZSP
|
||||||
/*********************************************************************************************\
|
int32_t EZ_ReceiveTCJoinHandler(int32_t res, const class SBuffer &buf) {
|
||||||
* Send specific EZS¨ messages
|
uint16_t srcAddr = buf.get16(2);
|
||||||
\*********************************************************************************************/
|
uint64_t ieeeAddr = buf.get64(4);
|
||||||
|
uint8_t status = buf.get8(12);
|
||||||
|
uint8_t decision = buf.get8(13);
|
||||||
|
uint16_t parentNw = buf.get16(14);
|
||||||
|
|
||||||
//
|
if (EMBER_DEVICE_LEFT != status) { // ignore message if the device is leaving
|
||||||
// Callback for loading Zigbee configuration from Flash, called by the state machine
|
zigbee_devices.updateDevice(srcAddr, ieeeAddr);
|
||||||
//
|
|
||||||
int32_t Z_Reset_Device(uint8_t value) {
|
char hex[20];
|
||||||
// TODO - GPIO is hardwired to GPIO4
|
Uint64toHex(ieeeAddr, hex, 64);
|
||||||
digitalWrite(4, value ? HIGH : LOW);
|
Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{"
|
||||||
return 0; // continue
|
"\"Status\":%d,\"IEEEAddr\":\"0x%s\",\"ShortAddr\":\"0x%04X\""
|
||||||
|
",\"ParentNetwork\":\"0x%04X\""
|
||||||
|
",\"Status\":%d,\"Decision\":%d"
|
||||||
|
"}}"),
|
||||||
|
ZIGBEE_STATUS_DEVICE_INDICATION, hex, srcAddr, parentNw,
|
||||||
|
status, decision
|
||||||
|
);
|
||||||
|
|
||||||
|
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED));
|
||||||
|
XdrvRulesProcess();
|
||||||
}
|
}
|
||||||
|
return -1;
|
||||||
//
|
|
||||||
// Send ZDO_IEEE_ADDR_REQ request to get IEEE long address
|
|
||||||
//
|
|
||||||
void Z_SendIEEEAddrReq(uint16_t shortaddr) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Send ACTIVE_EP_REQ to collect active endpoints for this address
|
|
||||||
//
|
|
||||||
void Z_SendActiveEpReq(uint16_t shortaddr) {
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Send AF Info Request
|
|
||||||
//
|
|
||||||
void Z_SendAFInfoRequest(uint16_t shortaddr) {
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // USE_ZIGBEE_EZSP
|
#endif // USE_ZIGBEE_EZSP
|
||||||
|
|
||||||
/*********************************************************************************************\
|
//
|
||||||
* Callbacks
|
// Parse incoming ZCL message. This code is common to ZNP and EZSP
|
||||||
\*********************************************************************************************/
|
//
|
||||||
|
void Z_IncomingMessage(ZCLFrame &zcl_received) {
|
||||||
|
uint16_t srcaddr = zcl_received.getSrcAddr();
|
||||||
// Aqara Occupancy behavior: the Aqara device only sends Occupancy: true events every 60 seconds.
|
uint16_t groupid = zcl_received.getGroupAddr();
|
||||||
// Here we add a timer so if we don't receive a Occupancy event for 90 seconds, we send Occupancy:false
|
uint16_t clusterid = zcl_received.getClusterId();
|
||||||
void Z_AqaraOccupancy(uint16_t shortaddr, uint16_t cluster, uint8_t endpoint, const JsonObject &json) {
|
uint8_t linkquality = zcl_received.getLinkQuality();
|
||||||
static const uint32_t OCCUPANCY_TIMEOUT = 90 * 1000; // 90 s
|
uint8_t srcendpoint = zcl_received.getSrcEndpoint();
|
||||||
// Read OCCUPANCY value if any
|
|
||||||
const JsonVariant &val_endpoint = GetCaseInsensitive(json, PSTR(OCCUPANCY));
|
|
||||||
if (nullptr != &val_endpoint) {
|
|
||||||
uint32_t occupancy = strToUInt(val_endpoint);
|
|
||||||
|
|
||||||
if (occupancy) {
|
|
||||||
zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, OCCUPANCY_TIMEOUT, cluster, endpoint, Z_CAT_VIRTUAL_OCCUPANCY, 0, &Z_OccupancyCallback);
|
|
||||||
} else {
|
|
||||||
zigbee_devices.resetTimersForDevice(shortaddr, 0 /* groupaddr */, Z_CAT_VIRTUAL_OCCUPANCY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Publish the received values once they have been coalesced
|
|
||||||
int32_t Z_PublishAttributes(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) {
|
|
||||||
const JsonObject *json = zigbee_devices.jsonGet(shortaddr);
|
|
||||||
if (json == nullptr) { return 0; } // don't crash if not found
|
|
||||||
|
|
||||||
zigbee_devices.jsonPublishFlush(shortaddr);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************************************\
|
|
||||||
* Global dispatcher for incoming messages
|
|
||||||
\*********************************************************************************************/
|
|
||||||
|
|
||||||
int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) {
|
|
||||||
uint16_t groupid = buf.get16(2);
|
|
||||||
uint16_t clusterid = buf.get16(4);
|
|
||||||
uint16_t srcaddr = buf.get16(6);
|
|
||||||
uint8_t srcendpoint = buf.get8(8);
|
|
||||||
uint8_t dstendpoint = buf.get8(9);
|
|
||||||
uint8_t wasbroadcast = buf.get8(10);
|
|
||||||
uint8_t linkquality = buf.get8(11);
|
|
||||||
uint8_t securityuse = buf.get8(12);
|
|
||||||
uint32_t timestamp = buf.get32(13);
|
|
||||||
uint8_t seqnumber = buf.get8(17);
|
|
||||||
|
|
||||||
bool defer_attributes = false; // do we defer attributes reporting to coalesce
|
bool defer_attributes = false; // do we defer attributes reporting to coalesce
|
||||||
|
|
||||||
ZCLFrame zcl_received = ZCLFrame::parseRawFrame(buf, 19, buf.get8(18), clusterid, groupid,
|
// log the packet details
|
||||||
srcaddr,
|
|
||||||
srcendpoint, dstendpoint, wasbroadcast,
|
|
||||||
linkquality, securityuse, seqnumber,
|
|
||||||
timestamp);
|
|
||||||
zcl_received.log();
|
zcl_received.log();
|
||||||
|
|
||||||
zigbee_devices.setLQI(srcaddr, linkquality);
|
zigbee_devices.setLQI(srcaddr, linkquality != 0xFF ? linkquality : 0xFE); // EFR32 has a different scale for LQI
|
||||||
|
|
||||||
char shortaddr[8];
|
char shortaddr[8];
|
||||||
snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%04X"), srcaddr);
|
snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%04X"), srcaddr);
|
||||||
|
@ -823,17 +852,180 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) {
|
||||||
Z_AutoResponder(srcaddr, clusterid, srcendpoint, json[F("ReadNames")]);
|
Z_AutoResponder(srcaddr, clusterid, srcendpoint, json[F("ReadNames")]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_ZIGBEE_EZSP
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Send ZDO Message
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
void EZ_SendZDO(uint16_t shortaddr, uint16_t cmd, const unsigned char *payload, size_t payload_len) {
|
||||||
|
SBuffer buf(payload_len + 20);
|
||||||
|
uint8_t seq = zigbee_devices.getNextSeqNumber(0x0000);
|
||||||
|
|
||||||
|
buf.add8(EMBER_OUTGOING_DIRECT); // 00
|
||||||
|
buf.add16(shortaddr); // dest addr
|
||||||
|
// ApsFrame
|
||||||
|
buf.add16(0x0000); // ZOD profile
|
||||||
|
buf.add16(cmd); // ZDO cmd in cluster
|
||||||
|
buf.add8(0); // srcEp
|
||||||
|
buf.add8(0); // dstEp
|
||||||
|
buf.add16(EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY | EMBER_APS_OPTION_RETRY); // APS frame
|
||||||
|
buf.add16(0x0000); // groupId
|
||||||
|
buf.add8(seq);
|
||||||
|
// end of ApsFrame
|
||||||
|
buf.add8(0x01); // tag TODO
|
||||||
|
buf.add8(payload_len + 1); // insert seq number
|
||||||
|
buf.add8(seq);
|
||||||
|
buf.addBuffer(payload, payload_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Send specific EZSP messages
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
int32_t EZ_IncomingMessage(int32_t res, const class SBuffer &buf) {
|
||||||
|
uint8_t msgtype = buf.get8(2); // see EZSP_EmberIncomingMessageType
|
||||||
|
bool wasbroadcast = (msgtype >= EMBER_INCOMING_MULTICAST) && (msgtype <= EMBER_INCOMING_BROADCAST_LOOPBACK);
|
||||||
|
uint16_t profileid = buf.get16(3); // HA = 0x0104, ZDO = 0x0000
|
||||||
|
uint16_t clusterid = buf.get16(5);
|
||||||
|
uint8_t srcendpoint = buf.get8(7);
|
||||||
|
uint8_t dstendpoint = buf.get8(8);
|
||||||
|
uint16_t apsoptions = buf.get16(9); // see EZSP_EmberApsOption, usually EMBER_APS_OPTION_ENABLE_ADDRESS_DISCOVERY
|
||||||
|
bool securityuse = (apsoptions & EMBER_APS_OPTION_ENCRYPTION) ? true : false;
|
||||||
|
uint16_t groupid = buf.get16(11);
|
||||||
|
uint8_t seqnumber = buf.get8(13);
|
||||||
|
uint8_t linkquality = buf.get8(14);
|
||||||
|
// uint8_t linkrsssi = buf.get8(15); // probably not used as there is no equivalent in Z-Stack
|
||||||
|
uint16_t srcaddr = buf.get16(16);
|
||||||
|
uint8_t bindingindex = buf.get8(18); // TODO not sure we need this one as a coordinator
|
||||||
|
uint8_t addressindex = buf.get8(19); // TODO not sure how to handle this one
|
||||||
|
// offset 20 is len, and buffer starts at offset 21
|
||||||
|
|
||||||
|
|
||||||
|
if ((0x0000 == profileid) && (0x00 == srcendpoint)) {
|
||||||
|
// ZDO request
|
||||||
|
SBuffer zdo_buf = buf.subBuffer(21, buf.get8(20));
|
||||||
|
switch (clusterid) {
|
||||||
|
case ZDO_Device_annce:
|
||||||
|
Z_ReceiveEndDeviceAnnonce(res, zdo_buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bool defer_attributes = false; // do we defer attributes reporting to coalesce
|
||||||
|
ZCLFrame zcl_received = ZCLFrame::parseRawFrame(buf, 21, buf.get8(20), clusterid, groupid,
|
||||||
|
srcaddr,
|
||||||
|
srcendpoint, dstendpoint, wasbroadcast,
|
||||||
|
linkquality, securityuse, seqnumber);
|
||||||
|
//
|
||||||
|
Z_IncomingMessage(zcl_received);
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Callback for loading Zigbee configuration from Flash, called by the state machine
|
||||||
|
//
|
||||||
|
int32_t Z_Reset_Device(uint8_t value) {
|
||||||
|
// TODO - GPIO is hardwired to GPIO4
|
||||||
|
digitalWrite(4, value ? HIGH : LOW);
|
||||||
|
return 0; // continue
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Default resolver
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf) {
|
||||||
|
// Default message handler for new messages
|
||||||
|
if (zigbee.init_phase) {
|
||||||
|
// if still during initialization phase, ignore any unexpected message
|
||||||
|
return -1; // ignore message
|
||||||
|
} else {
|
||||||
|
switch (buf.get8(0)) {
|
||||||
|
case EZSP_incomingMessageHandler:
|
||||||
|
return EZ_IncomingMessage(res, buf);
|
||||||
|
break;
|
||||||
|
case EZSP_trustCenterJoinHandler:
|
||||||
|
return EZ_ReceiveTCJoinHandler(res, buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_ZIGBEE_EZSP
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Callbacks
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
// Aqara Occupancy behavior: the Aqara device only sends Occupancy: true events every 60 seconds.
|
||||||
|
// Here we add a timer so if we don't receive a Occupancy event for 90 seconds, we send Occupancy:false
|
||||||
|
void Z_AqaraOccupancy(uint16_t shortaddr, uint16_t cluster, uint8_t endpoint, const JsonObject &json) {
|
||||||
|
static const uint32_t OCCUPANCY_TIMEOUT = 90 * 1000; // 90 s
|
||||||
|
// Read OCCUPANCY value if any
|
||||||
|
const JsonVariant &val_endpoint = GetCaseInsensitive(json, PSTR(OCCUPANCY));
|
||||||
|
if (nullptr != &val_endpoint) {
|
||||||
|
uint32_t occupancy = strToUInt(val_endpoint);
|
||||||
|
|
||||||
|
if (occupancy) {
|
||||||
|
zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, OCCUPANCY_TIMEOUT, cluster, endpoint, Z_CAT_VIRTUAL_OCCUPANCY, 0, &Z_OccupancyCallback);
|
||||||
|
} else {
|
||||||
|
zigbee_devices.resetTimersForDevice(shortaddr, 0 /* groupaddr */, Z_CAT_VIRTUAL_OCCUPANCY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Publish the received values once they have been coalesced
|
||||||
|
int32_t Z_PublishAttributes(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) {
|
||||||
|
const JsonObject *json = zigbee_devices.jsonGet(shortaddr);
|
||||||
|
if (json == nullptr) { return 0; } // don't crash if not found
|
||||||
|
|
||||||
|
zigbee_devices.jsonPublishFlush(shortaddr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Global dispatcher for incoming messages
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) {
|
||||||
|
uint16_t groupid = buf.get16(2);
|
||||||
|
uint16_t clusterid = buf.get16(4);
|
||||||
|
uint16_t srcaddr = buf.get16(6);
|
||||||
|
uint8_t srcendpoint = buf.get8(8);
|
||||||
|
uint8_t dstendpoint = buf.get8(9);
|
||||||
|
uint8_t wasbroadcast = buf.get8(10);
|
||||||
|
uint8_t linkquality = buf.get8(11);
|
||||||
|
uint8_t securityuse = buf.get8(12);
|
||||||
|
// uint32_t timestamp = buf.get32(13);
|
||||||
|
uint8_t seqnumber = buf.get8(17);
|
||||||
|
|
||||||
|
bool defer_attributes = false; // do we defer attributes reporting to coalesce
|
||||||
|
|
||||||
|
ZCLFrame zcl_received = ZCLFrame::parseRawFrame(buf, 19, buf.get8(18), clusterid, groupid,
|
||||||
|
srcaddr,
|
||||||
|
srcendpoint, dstendpoint, wasbroadcast,
|
||||||
|
linkquality, securityuse, seqnumber);
|
||||||
|
//
|
||||||
|
Z_IncomingMessage(zcl_received);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_ZIGBEE_ZNP
|
||||||
|
|
||||||
// Structure for the Dispatcher callbacks table
|
// Structure for the Dispatcher callbacks table
|
||||||
typedef struct Z_Dispatcher {
|
typedef struct Z_Dispatcher {
|
||||||
const uint8_t* match;
|
const uint8_t* match;
|
||||||
ZB_RecvMsgFunc func;
|
ZB_RecvMsgFunc func;
|
||||||
} Z_Dispatcher;
|
} Z_Dispatcher;
|
||||||
|
|
||||||
#ifdef USE_ZIGBEE_ZNP
|
|
||||||
|
|
||||||
// Ffilters based on ZNP frames
|
// Ffilters based on ZNP frames
|
||||||
ZBM(AREQ_AF_DATA_CONFIRM, Z_AREQ | Z_AF, AF_DATA_CONFIRM) // 4480
|
ZBM(AREQ_AF_DATA_CONFIRM, Z_AREQ | Z_AF, AF_DATA_CONFIRM) // 4480
|
||||||
ZBM(AREQ_AF_INCOMING_MESSAGE, Z_AREQ | Z_AF, AF_INCOMING_MSG) // 4481
|
ZBM(AREQ_AF_INCOMING_MESSAGE, Z_AREQ | Z_AF, AF_INCOMING_MSG) // 4481
|
||||||
|
@ -874,7 +1066,7 @@ int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf) {
|
||||||
// if still during initialization phase, ignore any unexpected message
|
// if still during initialization phase, ignore any unexpected message
|
||||||
return -1; // ignore message
|
return -1; // ignore message
|
||||||
} else {
|
} else {
|
||||||
for (uint32_t i = 0; i < sizeof(Z_DispatchTable)/sizeof(Z_Dispatcher); i++) {
|
for (uint32_t i = 0; i < ARRAY_SIZE(Z_DispatchTable); i++) {
|
||||||
if (Z_ReceiveMatchPrefix(buf, Z_DispatchTable[i].match)) {
|
if (Z_ReceiveMatchPrefix(buf, Z_DispatchTable[i].match)) {
|
||||||
(*Z_DispatchTable[i].func)(res, buf);
|
(*Z_DispatchTable[i].func)(res, buf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -495,7 +495,7 @@ int32_t ZigbeeProcessInputEZSP(class SBuffer &buf) {
|
||||||
bool overflow = frame_control & 0x01;
|
bool overflow = frame_control & 0x01;
|
||||||
bool callbackPending = frame_control & 0x04;
|
bool callbackPending = frame_control & 0x04;
|
||||||
bool security_enabled = frame_control & 0x8000;
|
bool security_enabled = frame_control & 0x8000;
|
||||||
if (frame_control != 0x0180) {
|
if (truncated || overflow || security_enabled) {
|
||||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("ZIG: specific frame_control 0x%04X"), frame_control);
|
AddLog_P2(LOG_LEVEL_INFO, PSTR("ZIG: specific frame_control 0x%04X"), frame_control);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -954,8 +954,8 @@ void CmndZbRestore(void) {
|
||||||
//
|
//
|
||||||
void CmndZbPermitJoin(void) {
|
void CmndZbPermitJoin(void) {
|
||||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||||
|
|
||||||
uint32_t payload = XdrvMailbox.payload;
|
uint32_t payload = XdrvMailbox.payload;
|
||||||
uint16_t dstAddr = 0xFFFC; // default addr
|
|
||||||
uint8_t duration = 60; // default 60s
|
uint8_t duration = 60; // default 60s
|
||||||
|
|
||||||
if (payload <= 0) {
|
if (payload <= 0) {
|
||||||
|
@ -964,7 +964,10 @@ void CmndZbPermitJoin(void) {
|
||||||
duration = 0xFF; // unlimited time
|
duration = 0xFF; // unlimited time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ZNP Version
|
||||||
#ifdef USE_ZIGBEE_ZNP
|
#ifdef USE_ZIGBEE_ZNP
|
||||||
|
uint16_t dstAddr = 0xFFFC; // default addr
|
||||||
|
|
||||||
SBuffer buf(34);
|
SBuffer buf(34);
|
||||||
buf.add8(Z_SREQ | Z_ZDO); // 25
|
buf.add8(Z_SREQ | Z_ZDO); // 25
|
||||||
buf.add8(ZDO_MGMT_PERMIT_JOIN_REQ); // 36
|
buf.add8(ZDO_MGMT_PERMIT_JOIN_REQ); // 36
|
||||||
|
@ -974,8 +977,17 @@ void CmndZbPermitJoin(void) {
|
||||||
buf.add8(0x00); // TCSignificance
|
buf.add8(0x00); // TCSignificance
|
||||||
|
|
||||||
ZigbeeZNPSend(buf.getBuffer(), buf.len());
|
ZigbeeZNPSend(buf.getBuffer(), buf.len());
|
||||||
|
|
||||||
#endif // USE_ZIGBEE_ZNP
|
#endif // USE_ZIGBEE_ZNP
|
||||||
|
|
||||||
|
// EZSP VERSION
|
||||||
|
#ifdef USE_ZIGBEE_EZSP
|
||||||
|
SBuffer buf(3);
|
||||||
|
buf.add16(EZSP_permitJoining);
|
||||||
|
buf.add8(duration);
|
||||||
|
ZigbeeEZSPSendCmd(buf.getBuffer(), buf.len(), true);
|
||||||
|
#endif // USE_ZIGBEE_EZSP
|
||||||
|
|
||||||
ResponseCmndDone();
|
ResponseCmndDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue