Merge pull request #8839 from s-hadinger/zigbee_july_2

Zigbee EZSP milestone 4
This commit is contained in:
Theo Arends 2020-07-02 23:25:21 +02:00 committed by GitHub
commit a39e97af5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 382 additions and 104 deletions

View File

@ -679,6 +679,7 @@
// if PANID == 0xFFFE, then the device will act as a Zigbee end-device (non-router), the parameters below are ignored
#define USE_ZIGBEE_EXTPANID 0xCCCCCCCCCCCCCCCCL // arbitrary extended PAN ID
#define USE_ZIGBEE_CHANNEL 11 // Zigbee Channel (11-26)
#define USE_ZIGBEE_TXRADIO_DBM 20 // Tx Radio power in dBm (only for EZSP, EFR32 can go up to 20 dBm)
#define USE_ZIGBEE_PRECFGKEY_L 0x0F0D0B0907050301L // note: changing requires to re-pair all devices
#define USE_ZIGBEE_PRECFGKEY_H 0x0D0C0A0806040200L // note: changing requires to re-pair all devices

View File

@ -559,7 +559,7 @@ struct {
uint64_t zb_precfgkey_h; // F28
uint16_t zb_pan_id; // F30
uint8_t zb_channel; // F32
uint8_t zb_free_byte; // F33
uint8_t zb_txradio_dbm; // F33
uint16_t pms_wake_interval; // F34
uint8_t config_version; // F36
uint8_t windmeter_pulses_x_rot; // F37

View File

@ -106,6 +106,7 @@ enum Zigbee_StateMachine_Instruction_Set {
#define ZI_WAIT_RECV_FUNC(x, m, f) { .i = { ZGB_INSTR_WAIT_RECV_CALL, sizeof(m), (x)} }, { .p = (const void*)(m) }, { .p = (const void*)(f) },
// Labels used in the State Machine -- internal only
const uint8_t ZIGBEE_LABEL_RESTART = 1; // Restart the state_machine in a different mode
const uint8_t ZIGBEE_LABEL_INIT_COORD = 10; // Start ZNP as coordinator
const uint8_t ZIGBEE_LABEL_START_COORD = 11; // Start ZNP as coordinator
const uint8_t ZIGBEE_LABEL_INIT_ROUTER = 12; // Init ZNP as router
@ -118,13 +119,16 @@ const uint8_t ZIGBEE_LABEL_BOOT_TIME_OUT = 18; // MCU has not rebooted
const uint8_t ZIGBEE_LABEL_FACT_RESET_ROUTER_DEVICE_POST = 19; // common post configuration for router and device
const uint8_t ZIGBEE_LABEL_READY = 20; // goto label 20 for main loop
const uint8_t ZIGBEE_LABEL_MAIN_LOOP = 21; // main loop
const uint8_t ZIGBEE_LABEL_NETWORK_CONFIGURED = 22; // main loop
const uint8_t ZIGBEE_LABEL_BAD_CONFIG = 23; // EZSP configuration is not the right one
const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_CLOSE = 30; // disable permit join
const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60 = 31; // enable permit join for 60 seconds
const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX = 32; // enable permit join for 60 seconds
// factory reset
// factory reset or reconfiguration
const uint8_t ZIGBEE_LABEL_FACT_RESET_COORD = 50; // main loop
const uint8_t ZIGBEE_LABEL_FACT_RESET_ROUTER = 51; // main loop
const uint8_t ZIGBEE_LABEL_FACT_RESET_DEVICE = 52; // main loop
const uint8_t ZIGBEE_LABEL_CONFIGURE_EZSP = 53; // main loop
// errors
const uint8_t ZIGBEE_LABEL_ABORT = 99; // goto label 99 in case of fatal error
const uint8_t ZIGBEE_LABEL_UNSUPPORTED_VERSION = 98; // Unsupported ZNP version
@ -371,7 +375,7 @@ ZBM(ZBR_PERMITJOINREQ, Z_SRSP | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, Z_SUCCESS) /
ZBM(ZBR_PERMITJOIN_AREQ_RSP, Z_AREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_RSP, 0x00, 0x00 /* srcAddr*/, Z_SUCCESS ) // 45B6000000
// Update the relevant commands with Settings
void Z_UpdateConfig(uint8_t zb_channel, uint16_t zb_pan_id, uint64_t zb_ext_panid, uint64_t zb_precfgkey_l, uint64_t zb_precfgkey_h) {
void ZNP_UpdateConfig(uint8_t zb_channel, uint16_t zb_pan_id, uint64_t zb_ext_panid, uint64_t zb_precfgkey_l, uint64_t zb_precfgkey_h) {
uint32_t zb_channel_mask = (1 << zb_channel);
ZBW(ZBR_PAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_PANID, 0x02 /* len */,
@ -422,26 +426,26 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
ZI_NOOP()
ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT)
ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT)
ZI_ON_RECV_UNEXPECTED(&Z_Recv_Default)
ZI_ON_RECV_UNEXPECTED(&ZNP_Recv_Default)
ZI_WAIT(10500) // wait for 10 seconds for Tasmota to stabilize
//ZI_MQTT_STATE(ZIGBEE_STATUS_BOOT, "Booting")
//ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "rebooting device")
ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_BOOT_TIME_OUT) // give a second chance
ZI_SEND(ZBS_RESET) // reboot cc2530 just in case we rebooted ESP8266 but not cc2530
ZI_WAIT_RECV_FUNC(5000, ZBR_RESET, &Z_Reboot) // timeout 5s
ZI_WAIT_RECV_FUNC(5000, ZBR_RESET, &ZNP_Reboot) // timeout 5s
ZI_GOTO(ZIGBEE_LABEL_BOOT_OK)
ZI_LABEL(ZIGBEE_LABEL_BOOT_TIME_OUT)
ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT)
ZI_SEND(ZBS_RESET) // reboot cc2530 just in case we rebooted ESP8266 but not cc2530
ZI_WAIT_RECV_FUNC(5000, ZBR_RESET, &Z_Reboot) // timeout 5s
ZI_WAIT_RECV_FUNC(5000, ZBR_RESET, &ZNP_Reboot) // timeout 5s
ZI_LABEL(ZIGBEE_LABEL_BOOT_OK)
ZI_WAIT(100)
ZI_LOG(LOG_LEVEL_DEBUG, kCheckingDeviceConfiguration) // Log Debug: checking device configuration
ZI_SEND(ZBS_VERSION) // check ZNP software version
ZI_WAIT_RECV_FUNC(2000, ZBR_VERSION, &Z_ReceiveCheckVersion) // Check if version is valid
ZI_WAIT_RECV_FUNC(2000, ZBR_VERSION, &ZNP_ReceiveCheckVersion) // Check if version is valid
// Dispatching whether coordinator, router or end-device
ZI_CALL(&Z_SwitchDeviceType, 0) // goto ZIGBEE_LABEL_INIT_ROUTER, ZIGBEE_LABEL_INIT_DEVICE or continue if coordinator
@ -476,9 +480,9 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
//ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "starting zigbee coordinator")
ZI_SEND(ZBS_STARTUPFROMAPP) // start coordinator
ZI_WAIT_RECV(2000, ZBR_STARTUPFROMAPP) // wait for sync ack of command
ZI_WAIT_UNTIL_FUNC(10000, AREQ_STARTUPFROMAPP, &Z_ReceiveStateChange) // wait for async message that coordinator started
ZI_WAIT_UNTIL_FUNC(10000, AREQ_STARTUPFROMAPP, &ZNP_ReceiveStateChange) // wait for async message that coordinator started
ZI_SEND(ZBS_GETDEVICEINFO) // GetDeviceInfo
ZI_WAIT_RECV_FUNC(2000, ZBR_GETDEVICEINFO, &Z_ReceiveDeviceInfo)
ZI_WAIT_RECV_FUNC(2000, ZBR_GETDEVICEINFO, &ZNP_ReceiveDeviceInfo)
//ZI_WAIT_RECV(2000, ZBR_GETDEVICEINFO) // memorize info
ZI_SEND(ZBS_ZDO_NODEDESCREQ) // Z_ZDO:nodeDescReq
ZI_WAIT_RECV(1000, ZBR_ZDO_NODEDESCREQ)
@ -537,7 +541,7 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
ZI_WAIT_RECV(1000, ZBR_W_OK)
// Now mark the device as ready, writing 0x55 in memory slot 0x0F00
ZI_SEND(ZBS_WNV_INITZNPHC) // Init NV ZNP Has Configured
ZI_WAIT_RECV_FUNC(1000, ZBR_WNV_INIT_OK, &Z_CheckNVWrite)
ZI_WAIT_RECV_FUNC(1000, ZBR_WNV_INIT_OK, &ZNP_CheckNVWrite)
ZI_SEND(ZBS_WNV_ZNPHC) // Write NV ZNP Has Configured
ZI_WAIT_RECV(1000, ZBR_WNV_OK)
@ -563,9 +567,9 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
ZI_WAIT_RECV(1000, ZBR_AF_REGISTER)
ZI_SEND(ZBS_STARTUPFROMAPP) // start router
ZI_WAIT_RECV(2000, ZBR_STARTUPFROMAPP) // wait for sync ack of command
ZI_WAIT_UNTIL_FUNC(0xFFFF, AREQ_STARTUPFROMAPP, &Z_ReceiveStateChange) // wait for async message that coordinator started
ZI_WAIT_UNTIL_FUNC(0xFFFF, AREQ_STARTUPFROMAPP, &ZNP_ReceiveStateChange) // wait for async message that coordinator started
ZI_SEND(ZBS_GETDEVICEINFO) // GetDeviceInfo
ZI_WAIT_RECV_FUNC(2000, ZBR_GETDEVICEINFO, &Z_ReceiveDeviceInfo)
ZI_WAIT_RECV_FUNC(2000, ZBR_GETDEVICEINFO, &ZNP_ReceiveDeviceInfo)
ZI_GOTO(ZIGBEE_LABEL_READY)
ZI_LABEL(ZIGBEE_LABEL_FACT_RESET_ROUTER) // Factory reset for router
@ -585,7 +589,7 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
// Now mark the device as ready, writing 0x55 in memory slot 0x0F00
ZI_SEND(ZBS_WNV_INITZNPHC) // Init NV ZNP Has Configured
ZI_WAIT_RECV_FUNC(1000, ZBR_WNV_INIT_OK, &Z_CheckNVWrite)
ZI_WAIT_RECV_FUNC(1000, ZBR_WNV_INIT_OK, &ZNP_CheckNVWrite)
ZI_SEND(ZBS_WNV_ZNPHC) // Write NV ZNP Has Configured
ZI_WAIT_RECV(1000, ZBR_WNV_OK)
@ -632,11 +636,6 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
#ifdef USE_ZIGBEE_EZSP
// Update the relevant commands with Settings
void Z_UpdateConfig(uint8_t zb_channel, uint16_t zb_pan_id, uint64_t zb_ext_panid, uint64_t zb_precfgkey_l, uint64_t zb_precfgkey_h) {
}
// patterns for EZSP
// wait for RSTACK, meaning the device booted
@ -666,8 +665,8 @@ ZBM(ZBR_SET_OK, EZSP_setConfigurationValue, 0x00 /*high*/, 0x00 /*ok*/) // 53
ZBM(ZBR_SET_OK2, 0x00, 0x00 /*high*/, 0x00 /*ok*/) // 000000 - TODO why does setting EZSP_CONFIG_PACKET_BUFFER_COUNT has a different response?
// Read some configuration values
ZBM(ZBS_GET_APS_UNI, EZSP_getConfigurationValue, 0x00 /*high*/, EZSP_CONFIG_APS_UNICAST_MESSAGE_COUNT) // 520003
ZBM(ZBR_GET_OK, EZSP_getConfigurationValue, 0x00 /*high*/, 0x00 /*ok*/) // 5200 - followed by the value
// ZBM(ZBS_GET_APS_UNI, EZSP_getConfigurationValue, 0x00 /*high*/, EZSP_CONFIG_APS_UNICAST_MESSAGE_COUNT) // 520003
// ZBM(ZBR_GET_OK, EZSP_getConfigurationValue, 0x00 /*high*/, 0x00 /*ok*/) // 5200 - followed by the value
// Add Endpoints
ZBM(ZBS_ADD_ENDPOINT1, EZSP_addEndpoint, 0x00 /*high*/, 0x01 /*ep*/, Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA),
@ -697,7 +696,7 @@ ZBM(ZBR_SET_CONCENTRATOR, EZSP_setConcentrator, 0x00 /*high*/, 0x00 /*ok*/)
// 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*/,
ZBR(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"
@ -715,7 +714,7 @@ ZBM(ZBR_SET_SECURITY, EZSP_setInitialSecurityState, 0x00 /*high*/, 0x00 /*st
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
EZSP_HOST_WILL_NOT_SUPPLY_REPLY) // 55000220
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,
@ -724,12 +723,16 @@ ZBM(ZBS_SET_POLICY_06, EZSP_setPolicy, 0x00 /*high*/, EZSP_APP_KEY_REQUEST_PO
EZSP_DENY_APP_KEY_REQUESTS) // 55000660
ZBM(ZBR_SET_POLICY_XX, EZSP_setPolicy, 0x00 /*high*/, 0x00 /*status*/)
// networkInit - restart the network from previous settings
ZBM(ZBS_NETWORK_INIT, EZSP_networkInit, 0x00 /*high*/, 0x00, 0x00) // 17000000
ZBM(ZBR_NETWORK_INIT, EZSP_networkInit, 0x00 /*high*/, 0x00 /*status*/) // 170000
// formNetwork - i.e. start zigbee network as coordinator
ZBM(ZBS_FORM_NETWORK, EZSP_formNetwork, 0x00 /*high*/,
ZBR(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_TXRADIO_DBM /*radioTxPower*/,
USE_ZIGBEE_CHANNEL /*channel*/,
EMBER_USE_MAC_ASSOCIATION,
0xFF,0xFF, /*nwkManagerId, unused*/
@ -739,34 +742,103 @@ ZBM(ZBS_FORM_NETWORK, EZSP_formNetwork, 0x00 /*high*/,
ZBM(ZBR_FORM_NETWORK, EZSP_formNetwork, 0x00 /*high*/, 0x00 /*status*/) // 1E0000
ZBM(ZBR_NETWORK_UP, EZSP_stackStatusHandler, 0x00 /*high*/, EMBER_NETWORK_UP) // 190090
// leaveNetwork
ZBR(ZBS_LEAVE_NETWORK, EZSP_leaveNetwork, 0x00 /*high*/) // 2000
ZBM(ZBR_LEAVE_NETWORK, EZSP_leaveNetwork, 0x00 /*high*/) // 2000, we don't care whether it succeeeded or the network was not up
// 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
ZBR(ZBR_CHECK_NETW_PARM, EZSP_getNetworkParameters, 0x00 /*high*/,
0x00 /*status*/,
EMBER_COORDINATOR /*0x01*/,
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),
USE_ZIGBEE_TXRADIO_DBM /*radioTxPower*/,
USE_ZIGBEE_CHANNEL /*channel*/,
) // 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
// getCurrentSecurityState
// TODO double check the security bitmask
ZBM(ZBS_GET_CURR_SEC, EZSP_getCurrentSecurityState, 0x00 /*high*/) // 6900
ZBR(ZBR_GET_CURR_SEC, EZSP_getCurrentSecurityState, 0x00 /*high*/,
0x00 /*status*/,
0x7C, 0x00 /*Current Security Bitmask*/,
) // 6900...
/*********************************************************************************************\
* Update the relevant commands with Settings
\*********************************************************************************************/
//
void EZ_UpdateConfig(uint8_t zb_channel, uint16_t zb_pan_id, uint64_t zb_ext_panid, uint64_t zb_precfgkey_l, uint64_t zb_precfgkey_h, uint8_t zb_txradio_dbm) {
uint8_t txradio = zb_txradio_dbm;
// restrict txradio to acceptable range, and use default otherwise
if (txradio == 0) { txradio = USE_ZIGBEE_TXRADIO_DBM; }
if (txradio > 20) { txradio = USE_ZIGBEE_TXRADIO_DBM; }
ZBW(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(zb_precfgkey_l), Z_B1(zb_precfgkey_l), Z_B2(zb_precfgkey_l), Z_B3(zb_precfgkey_l),
Z_B4(zb_precfgkey_l), Z_B5(zb_precfgkey_l), Z_B6(zb_precfgkey_l), Z_B7(zb_precfgkey_l),
Z_B0(zb_precfgkey_h), Z_B1(zb_precfgkey_h), Z_B2(zb_precfgkey_h), Z_B3(zb_precfgkey_h),
Z_B4(zb_precfgkey_h), Z_B5(zb_precfgkey_h), Z_B6(zb_precfgkey_h), Z_B7(zb_precfgkey_h),
0x00 /*sequence*/,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*trustcenter*/
)
ZBW(ZBS_FORM_NETWORK, EZSP_formNetwork, 0x00 /*high*/,
Z_B0(zb_ext_panid), Z_B1(zb_ext_panid), Z_B2(zb_ext_panid), Z_B3(zb_ext_panid),
Z_B4(zb_ext_panid), Z_B5(zb_ext_panid), Z_B6(zb_ext_panid), Z_B7(zb_ext_panid),
Z_B0(zb_pan_id), Z_B1(zb_pan_id),
txradio /*radioTxPower*/,
zb_channel /*channel*/,
EMBER_USE_MAC_ASSOCIATION,
0xFF,0xFF, /*nwkManagerId, unused*/
0x00, /*nwkUpdateId, unused*/
0x00,0x00,0x00,0x00, /*NWK channel mask, unused*/
) // 1E00...
ZBW(ZBR_CHECK_NETW_PARM, EZSP_getNetworkParameters, 0x00 /*high*/,
0x00 /*status*/,
EMBER_COORDINATOR /*0x01*/,
Z_B0(zb_ext_panid), Z_B1(zb_ext_panid), Z_B2(zb_ext_panid), Z_B3(zb_ext_panid),
Z_B4(zb_ext_panid), Z_B5(zb_ext_panid), Z_B6(zb_ext_panid), Z_B7(zb_ext_panid),
Z_B0(zb_pan_id), Z_B1(zb_pan_id),
txradio /*radioTxPower*/,
zb_channel /*channel*/,
) // 2800...
}
static const Zigbee_Instruction zb_prog[] PROGMEM = {
ZI_LABEL(0)
ZI_NOOP()
ZI_CALL(EZ_Set_ResetConfig, 0) // for the firt pass, don't do a reset_config
ZI_LABEL(ZIGBEE_LABEL_RESTART)
ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT)
ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT)
ZI_ON_RECV_UNEXPECTED(&Z_Recv_Default)
ZI_ON_RECV_UNEXPECTED(&EZ_Recv_Default)
ZI_WAIT(10500) // wait for 10 seconds for Tasmota to stabilize
// Hardware reset
ZI_LOG(LOG_LEVEL_INFO, kResettingDevice) // Log Debug: resetting EZSP device
ZI_CALL(&Z_Reset_Device, 0) // LOW = reset
ZI_CALL(&EZ_Reset_Device, 0) // LOW = reset
ZI_WAIT(100) // wait for .1 second
ZI_CALL(&Z_Reset_Device, 1) // HIGH = release reset
ZI_CALL(&EZ_Reset_Device, 1) // HIGH = release reset
// wait for device to start
ZI_WAIT_UNTIL(5000, ZBR_RSTACK) // wait for RSTACK message
// Init device and probe version
ZI_SEND(ZBS_VERSION) ZI_WAIT_RECV_FUNC(1000, ZBR_VERSION, &Z_ReceiveCheckVersion) // check EXT PAN ID
ZI_SEND(ZBS_VERSION) ZI_WAIT_RECV_FUNC(1000, ZBR_VERSION, &EZ_ReceiveCheckVersion) // check EXT PAN ID
// configure EFR32
ZI_MQTT_STATE(ZIGBEE_STATUS_STARTING, kConfiguredCoord)
@ -786,7 +858,7 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
// read configuration
// TODO - not sure it's useful
//ZI_SEND(ZBS_GET_APS_UNI) ZI_WAIT_RECV_FUNC(500, ZBR_GET_OK, &Z_ReadAPSUnicastMessage)
//ZI_SEND(ZBS_GET_APS_UNI) ZI_WAIT_RECV_FUNC(500, ZBR_GET_OK, &EZ_ReadAPSUnicastMessage)
// add endpoint 0x01 and 0x0B
ZI_SEND(ZBS_ADD_ENDPOINT1) ZI_WAIT_RECV(500, ZBR_ADD_ENDPOINT)
@ -796,21 +868,52 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
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)
// set encryption keys
ZI_SEND(ZBS_SET_SECURITY) ZI_WAIT_RECV(500, ZBR_SET_SECURITY)
// Decide whether we try 'networkInit()' to restore configuration, or create a new network
ZI_CALL(&EZ_GotoIfResetConfig, ZIGBEE_LABEL_CONFIGURE_EZSP) // goto ZIGBEE_LABEL_CONFIGURE_EZSP if reset_config is set
// ZI_GOTO(ZIGBEE_LABEL_CONFIGURE_EZSP)
// // Try networkInit to restore settings, and check if network comes up
ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_BAD_CONFIG) //
ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_BAD_CONFIG)
ZI_SEND(ZBS_NETWORK_INIT) ZI_WAIT_RECV(500, ZBR_NETWORK_INIT)
ZI_WAIT_RECV(1500, ZBR_NETWORK_UP) // wait for network to start
// check if configuration is ok
ZI_SEND(ZBS_GET_CURR_SEC) ZI_WAIT_RECV(500, ZBR_GET_CURR_SEC)
ZI_SEND(ZBS_GET_NETW_PARM) ZI_WAIT_RECV(500, ZBR_CHECK_NETW_PARM)
// all ok, proceed to next step
ZI_GOTO(ZIGBEE_LABEL_NETWORK_CONFIGURED)
ZI_LABEL(ZIGBEE_LABEL_BAD_CONFIG)
ZI_MQTT_STATE(ZIGBEE_STATUS_RESET_CONF, kResetting)
ZI_CALL(EZ_Set_ResetConfig, 1) // change mode to reset_config
ZI_GOTO(ZIGBEE_LABEL_RESTART) // restart state_machine
ZI_LABEL(ZIGBEE_LABEL_CONFIGURE_EZSP)
// Set back normal error handlers
ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT)
ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT)
// 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
ZI_LABEL(ZIGBEE_LABEL_NETWORK_CONFIGURED)
// Set back normal error handlers
ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT)
ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT)
// 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_SEND(ZBS_GET_EUI64) ZI_WAIT_RECV_FUNC(500, ZBR_GET_EUI64, &EZ_GetEUI64)
ZI_SEND(ZBS_GET_NODEID) ZI_WAIT_RECV_FUNC(500, ZBR_GET_NODEID, &EZ_GetNodeId)
ZI_SEND(ZBS_GET_NETW_PARM) ZI_WAIT_RECV_FUNC(500, ZBR_GET_NETW_PARM, &EZ_NetworkParameters)
ZI_LABEL(ZIGBEE_LABEL_READY)
ZI_MQTT_STATE(ZIGBEE_STATUS_OK, kStarted)

View File

@ -24,8 +24,8 @@
* Parsers for incoming EZSP messages
\*********************************************************************************************/
// EZSP: received ASH RSTACK frame, indicating that the MCU finished boot
int32_t Z_EZSP_RSTACK(uint8_t reset_code) {
// EZSP: received ASH "RSTACK" frame, indicating that the MCU finished boot
int32_t EZ_RSTACK(uint8_t reset_code) {
const char *reason_str;
switch (reset_code) {
@ -47,8 +47,8 @@ int32_t Z_EZSP_RSTACK(uint8_t reset_code) {
XdrvRulesProcess();
}
// EZSP: received ASH ERROR frame, indicating that the MCU finished boot
int32_t Z_EZSP_ERROR(uint8_t error_code) {
// EZSP: received ASH "ERROR" frame, indicating that the MCU finished boot
int32_t EZ_ERROR(uint8_t error_code) {
const char *reason_str;
switch (error_code) {
@ -64,13 +64,59 @@ int32_t Z_EZSP_ERROR(uint8_t error_code) {
XdrvRulesProcess();
}
int32_t Z_ReadAPSUnicastMessage(int32_t res, class SBuffer &buf) {
int32_t EZ_ReadAPSUnicastMessage(int32_t res, class SBuffer &buf) {
// Called when receiving a response from getConfigurationValue
// Value is in bytes 2+3
uint16_t value = buf.get16(2);
return res;
}
/*********************************************************************************************\
* Parsers for incoming EZSP messages
\*********************************************************************************************/
//
// Handle a "getEui64" incoming message
//
int32_t EZ_GetEUI64(int32_t res, class SBuffer &buf) {
localIEEEAddr = buf.get64(2);
return res;
}
//
// Handle a "getEui64" incoming message
//
int32_t EZ_GetNodeId(int32_t res, class SBuffer &buf) {
localShortAddr = buf.get8(2);
return res;
}
//
// Handle a "getNetworkParameters" incoming message
//
int32_t EZ_NetworkParameters(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;
}
#endif // USE_ZIGBEE_EZSP
@ -128,7 +174,7 @@ int32_t Z_EZSPNetworkParameters(int32_t res, class SBuffer &buf) {
//
// Handle a "Receive Device Info" incoming message
//
int32_t Z_ReceiveDeviceInfo(int32_t res, class SBuffer &buf) {
int32_t ZNP_ReceiveDeviceInfo(int32_t res, class SBuffer &buf) {
// Ex= 6700.00.6263151D004B1200.0000.07.09.02.83869991
// IEEE Adr (8 bytes) = 0x00124B001D156362
// Short Addr (2 bytes) = 0x0000
@ -174,7 +220,7 @@ int32_t Z_ReceiveDeviceInfo(int32_t res, class SBuffer &buf) {
return res;
}
int32_t Z_CheckNVWrite(int32_t res, class SBuffer &buf) {
int32_t ZNP_CheckNVWrite(int32_t res, class SBuffer &buf) {
// Check the status after NV Init "ZNP Has Configured"
// Good response should be 610700 or 610709 (Success or Created)
// We only filter the response on 6107 and check the code in this function
@ -186,7 +232,7 @@ int32_t Z_CheckNVWrite(int32_t res, class SBuffer &buf) {
}
}
int32_t Z_Reboot(int32_t res, class SBuffer &buf) {
int32_t ZNP_Reboot(int32_t res, class SBuffer &buf) {
// print information about the reboot of device
// 4180.02.02.00.02.06.03
//
@ -221,8 +267,8 @@ int32_t Z_Reboot(int32_t res, class SBuffer &buf) {
}
}
int32_t Z_ReceiveCheckVersion(int32_t res, class SBuffer &buf) {
#ifdef USE_ZIGBEE_ZNP
int32_t ZNP_ReceiveCheckVersion(int32_t res, class SBuffer &buf) {
// check that the version is supported
// typical version for ZNP 1.2
// 61020200-02.06.03.D9143401.0200000000
@ -251,9 +297,11 @@ int32_t Z_ReceiveCheckVersion(int32_t res, class SBuffer &buf) {
} else {
return ZIGBEE_LABEL_UNSUPPORTED_VERSION; // abort
}
}
#endif // USE_ZIGBEE_ZNP
#ifdef USE_ZIGBEE_EZSP
int32_t EZ_ReceiveCheckVersion(int32_t res, class SBuffer &buf) {
uint8_t protocol_version = buf.get8(2);
uint8_t stack_type = buf.get8(3);
uint16_t stack_version = buf.get16(4);
@ -278,9 +326,25 @@ int32_t Z_ReceiveCheckVersion(int32_t res, class SBuffer &buf) {
} else {
return ZIGBEE_LABEL_UNSUPPORTED_VERSION; // abort
}
#endif // USE_ZIGBEE_EZSP
}
static bool EZ_reset_config = false;
// Set or clear reset_config
int32_t EZ_Set_ResetConfig(uint8_t value) {
EZ_reset_config = value ? true : false;
return 0;
}
// checks if we need to reset the configuration of the device
// if reset_config == 0, continue
// if reset_config == 1, goto ZIGBEE_LABEL_CONFIGURE_EZSP
int32_t EZ_GotoIfResetConfig(uint8_t value) {
if (EZ_reset_config) { return ZIGBEE_LABEL_CONFIGURE_EZSP; }
else { return 0; }
}
#endif // USE_ZIGBEE_EZSP
// checks the device type (coordinator, router, end-device)
// If coordinator continue
// If router goto ZIGBEE_LABEL_START_ROUTER
@ -308,7 +372,7 @@ bool Z_ReceiveMatchPrefix(const class SBuffer &buf, const uint8_t *match) {
//
// Handle Permit Join response
//
int32_t Z_ReceivePermitJoinStatus(int32_t res, const class SBuffer &buf) {
int32_t ZNP_ReceivePermitJoinStatus(int32_t res, const class SBuffer &buf) {
// we received a PermitJoin status change
uint8_t duration = buf.get8(2);
uint8_t status_code;
@ -335,7 +399,10 @@ int32_t Z_ReceivePermitJoinStatus(int32_t res, const class SBuffer &buf) {
return -1;
}
int32_t Z_ReceiveNodeDesc(int32_t res, const class SBuffer &buf) {
//
// ZNP only
//
int32_t ZNP_ReceiveNodeDesc(int32_t res, const class SBuffer &buf) {
// Received ZDO_NODE_DESC_RSP
Z_ShortAddress srcAddr = buf.get16(2);
uint8_t status = buf.get8(4);
@ -380,11 +447,19 @@ int32_t Z_ReceiveNodeDesc(int32_t res, const class SBuffer &buf) {
//
int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf) {
// Received ZDO_ACTIVE_EP_RSP
Z_ShortAddress srcAddr = buf.get16(2);
#ifdef USE_ZIGBEE_ZNP
// Z_ShortAddress srcAddr = buf.get16(2);
uint8_t status = buf.get8(4);
Z_ShortAddress nwkAddr = buf.get16(5);
uint8_t activeEpCount = buf.get8(7);
uint8_t* activeEpList = (uint8_t*) buf.charptr(8);
#endif
#ifdef USE_ZIGBEE_EZSP
uint8_t status = buf.get8(0);
Z_ShortAddress nwkAddr = buf.get16(1);
uint8_t activeEpCount = buf.get8(3);
uint8_t* activeEpList = (uint8_t*) buf.charptr(4);
#endif
for (uint32_t i = 0; i < activeEpCount; i++) {
zigbee_devices.addEndpoint(nwkAddr, activeEpList[i]);
@ -409,12 +484,22 @@ int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf) {
//
// Handle IEEEAddr incoming message
//
// Same works for both ZNP and EZSP
int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf) {
#ifdef USE_ZIGBEE_ZNP
uint8_t status = buf.get8(2);
Z_IEEEAddress ieeeAddr = buf.get64(3);
Z_ShortAddress nwkAddr = buf.get16(11);
// uint8_t startIndex = buf.get8(13); // not used
// uint8_t numAssocDev = buf.get8(14);
#endif // USE_ZIGBEE_ZNP
#ifdef USE_ZIGBEE_EZSP
uint8_t status = buf.get8(0);
Z_IEEEAddress ieeeAddr = buf.get64(1);
Z_ShortAddress nwkAddr = buf.get16(9);
// uint8_t numAssocDev = buf.get8(11);
// uint8_t startIndex = buf.get8(12); // not used
#endif // USE_ZIGBEE_EZSP
if (0 == status) { // SUCCESS
zigbee_devices.updateDevice(nwkAddr, ieeeAddr);
@ -439,7 +524,7 @@ int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf) {
// Report any AF_DATA_CONFIRM message
// Ex: {"ZbConfirm":{"Endpoint":1,"Status":0,"StatusMessage":"SUCCESS"}}
//
int32_t Z_DataConfirm(int32_t res, const class SBuffer &buf) {
int32_t ZNP_DataConfirm(int32_t res, const class SBuffer &buf) {
uint8_t status = buf.get8(2);
uint8_t endpoint = buf.get8(3);
//uint8_t transId = buf.get8(4); // unused
@ -471,7 +556,7 @@ int32_t Z_DataConfirm(int32_t res, const class SBuffer &buf) {
// 0x08: Starting as ZigBee Coordinator
// 0x09: Started as ZigBee Coordinator
// 0x0A: Device has lost information about its parent
int32_t Z_ReceiveStateChange(int32_t res, const class SBuffer &buf) {
int32_t ZNP_ReceiveStateChange(int32_t res, const class SBuffer &buf) {
uint8_t state = buf.get8(2);
const char * msg = nullptr;
@ -531,9 +616,9 @@ int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) {
#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);
Z_ShortAddress nwkAddr = buf.get16(0);
Z_IEEEAddress ieeeAddr = buf.get64(2);
uint8_t capabilities = buf.get8(10);
#endif
zigbee_devices.updateDevice(nwkAddr, ieeeAddr);
@ -562,7 +647,7 @@ int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) {
// Handle Receive TC Dev Ind incoming message
// 45CA
//
int32_t Z_ReceiveTCDevInd(int32_t res, const class SBuffer &buf) {
int32_t ZNP_ReceiveTCDevInd(int32_t res, const class SBuffer &buf) {
Z_ShortAddress srcAddr = buf.get16(2);
Z_IEEEAddress ieeeAddr = buf.get64(4);
Z_ShortAddress parentNw = buf.get16(12);
@ -585,7 +670,7 @@ int32_t Z_ReceiveTCDevInd(int32_t res, const class SBuffer &buf) {
//
// Handle Bind Rsp incoming message
//
int32_t Z_BindRsp(int32_t res, const class SBuffer &buf) {
int32_t ZNP_BindRsp(int32_t res, const class SBuffer &buf) {
Z_ShortAddress nwkAddr = buf.get16(2);
uint8_t status = buf.get8(4);
@ -608,7 +693,7 @@ int32_t Z_BindRsp(int32_t res, const class SBuffer &buf) {
//
// Handle Unbind Rsp incoming message
//
int32_t Z_UnbindRsp(int32_t res, const class SBuffer &buf) {
int32_t ZNP_UnbindRsp(int32_t res, const class SBuffer &buf) {
Z_ShortAddress nwkAddr = buf.get16(2);
uint8_t status = buf.get8(4);
@ -629,7 +714,7 @@ int32_t Z_UnbindRsp(int32_t res, const class SBuffer &buf) {
//
// Handle MgMt Bind Rsp incoming message
//
int32_t Z_MgmtBindRsp(int32_t res, const class SBuffer &buf) {
int32_t ZNP_MgmtBindRsp(int32_t res, const class SBuffer &buf) {
uint16_t shortaddr = buf.get16(2);
uint8_t status = buf.get8(4);
uint8_t bind_total = buf.get8(5);
@ -667,7 +752,7 @@ int32_t Z_MgmtBindRsp(int32_t res, const class SBuffer &buf) {
dstep = buf.get8(idx + 20);
idx += 21;
} else {
//AddLog_P2(LOG_LEVEL_INFO, PSTR("Z_MgmtBindRsp unknwon address mode %d"), addrmode);
//AddLog_P2(LOG_LEVEL_INFO, PSTR("ZNP_MgmtBindRsp unknwon address mode %d"), addrmode);
break; // abort for any other value since we don't know the length of the field
}
@ -705,6 +790,9 @@ void Z_SendIEEEAddrReq(uint16_t shortaddr) {
ZigbeeZNPSend(IEEEAddrReq, sizeof(IEEEAddrReq));
#endif
#ifdef USE_ZIGBEE_EZSP
// TODO
#endif
}
//
@ -725,17 +813,15 @@ void Z_SendActiveEpReq(uint16_t shortaddr) {
// Send AF Info Request
//
void Z_SendAFInfoRequest(uint16_t shortaddr) {
#ifdef USE_ZIGBEE_ZNP
uint8_t endpoint = zigbee_devices.findFirstEndpoint(shortaddr);
if (0x00 == endpoint) { endpoint = 0x01; } // if we don't know the endpoint, try 0x01
uint8_t transacid = zigbee_devices.getNextSeqNumber(shortaddr);
uint8_t AFInfoReq[] = { Z_SREQ | Z_AF, AF_DATA_REQUEST, Z_B0(shortaddr), Z_B1(shortaddr), endpoint,
0x01, 0x00, 0x00, transacid, 0x30, 0x1E, 3 + 2*sizeof(uint16_t),
0x00, transacid, ZCL_READ_ATTRIBUTES, 0x04, 0x00, 0x05, 0x00
};
ZigbeeZNPSend(AFInfoReq, sizeof(AFInfoReq));
#endif
uint8_t InfoReq[] = { 0x04, 0x00, 0x05, 0x00 };
ZigbeeZCLSend_Raw(shortaddr, 0x0000 /*group*/, 0x0000 /*cluster*/, endpoint, ZCL_READ_ATTRIBUTES,
false /*clusterSpecific*/, 0x0000 /*manuf*/,
InfoReq, sizeof(InfoReq), true /*needResponse*/, transacid);
}
@ -773,8 +859,9 @@ int32_t EZ_ReceiveTCJoinHandler(int32_t res, const class SBuffer &buf) {
#endif // USE_ZIGBEE_EZSP
//
// Parse incoming ZCL message. This code is common to ZNP and EZSP
// Parse incoming ZCL message.
//
// This code is common to ZNP and EZSP
void Z_IncomingMessage(ZCLFrame &zcl_received) {
uint16_t srcaddr = zcl_received.getSrcAddr();
uint16_t groupid = zcl_received.getGroupAddr();
@ -862,9 +949,11 @@ void Z_IncomingMessage(ZCLFrame &zcl_received) {
\*********************************************************************************************/
void EZ_SendZDO(uint16_t shortaddr, uint16_t cmd, const unsigned char *payload, size_t payload_len) {
SBuffer buf(payload_len + 20);
SBuffer buf(payload_len + 22);
uint8_t seq = zigbee_devices.getNextSeqNumber(0x0000);
buf.add16(EZSP_sendUnicast);
buf.add8(EMBER_OUTGOING_DIRECT); // 00
buf.add16(shortaddr); // dest addr
// ApsFrame
@ -880,6 +969,8 @@ void EZ_SendZDO(uint16_t shortaddr, uint16_t cmd, const unsigned char *payload,
buf.add8(payload_len + 1); // insert seq number
buf.add8(seq);
buf.addBuffer(payload, payload_len);
ZigbeeEZSPSendCmd(buf.buf(), buf.len(), true);
}
/*********************************************************************************************\
@ -907,10 +998,17 @@ int32_t EZ_IncomingMessage(int32_t res, const class SBuffer &buf) {
if ((0x0000 == profileid) && (0x00 == srcendpoint)) {
// ZDO request
SBuffer zdo_buf = buf.subBuffer(21, buf.get8(20));
// Since ZDO messages start with a sequence number, we skip it
SBuffer zdo_buf = buf.subBuffer(22, buf.get8(20) - 1);
switch (clusterid) {
case ZDO_Device_annce:
Z_ReceiveEndDeviceAnnonce(res, zdo_buf);
return Z_ReceiveEndDeviceAnnonce(res, zdo_buf);
break;
case ZDO_Active_EP_rsp:
return Z_ReceiveActiveEp(res, zdo_buf);
break;
case ZDO_IEEE_addr_rsp:
return Z_ReceiveIEEEAddr(res, zdo_buf);
break;
}
} else {
@ -928,7 +1026,7 @@ int32_t EZ_IncomingMessage(int32_t res, const class SBuffer &buf) {
//
// Callback for loading Zigbee configuration from Flash, called by the state machine
//
int32_t Z_Reset_Device(uint8_t value) {
int32_t EZ_Reset_Device(uint8_t value) {
// TODO - GPIO is hardwired to GPIO4
digitalWrite(4, value ? HIGH : LOW);
return 0; // continue
@ -938,13 +1036,15 @@ int32_t Z_Reset_Device(uint8_t value) {
* Default resolver
\*********************************************************************************************/
int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf) {
int32_t EZ_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)) {
uint16_t ezsp_command_index = buf.get16(0);
switch (ezsp_command_index) {
case EZSP_incomingMessageHandler:
return EZ_IncomingMessage(res, buf);
break;
@ -990,6 +1090,48 @@ int32_t Z_PublishAttributes(uint16_t shortaddr, uint16_t groupaddr, uint16_t clu
return 1;
}
/*********************************************************************************************\
* Global dispatcher for incoming messages
\*********************************************************************************************/
#ifdef USE_ZIGBEE_ZNP
int32_t ZNP_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;
}
//
// 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
}
#endif // USE_ZIGBEE_ZNP
/*********************************************************************************************\
* Global dispatcher for incoming messages
\*********************************************************************************************/
@ -1022,45 +1164,31 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) {
// Structure for the Dispatcher callbacks table
typedef struct Z_Dispatcher {
const uint8_t* match;
uint8_t match[2];
ZB_RecvMsgFunc func;
} Z_Dispatcher;
// Ffilters based on ZNP frames
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_STATE_CHANGE_IND, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND) // 45C0
ZBM(AREQ_END_DEVICE_ANNCE_IND, Z_AREQ | Z_ZDO, ZDO_END_DEVICE_ANNCE_IND) // 45C1
ZBM(AREQ_END_DEVICE_TC_DEV_IND, Z_AREQ | Z_ZDO, ZDO_TC_DEV_IND) // 45CA
ZBM(AREQ_PERMITJOIN_OPEN_XX, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND ) // 45CB
ZBM(AREQ_ZDO_ACTIVEEPRSP, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP) // 4585
ZBM(AREQ_ZDO_SIMPLEDESCRSP, Z_AREQ | Z_ZDO, ZDO_SIMPLE_DESC_RSP) // 4584
ZBM(AREQ_ZDO_IEEE_ADDR_RSP, Z_AREQ | Z_ZDO, ZDO_IEEE_ADDR_RSP) // 4581
ZBM(AREQ_ZDO_BIND_RSP, Z_AREQ | Z_ZDO, ZDO_BIND_RSP) // 45A1
ZBM(AREQ_ZDO_UNBIND_RSP, Z_AREQ | Z_ZDO, ZDO_UNBIND_RSP) // 45A2
ZBM(AREQ_ZDO_MGMT_BIND_RSP, Z_AREQ | Z_ZDO, ZDO_MGMT_BIND_RSP) // 45B3
// Dispatcher callbacks table
const Z_Dispatcher Z_DispatchTable[] PROGMEM = {
{ AREQ_AF_DATA_CONFIRM, &Z_DataConfirm },
{ AREQ_AF_INCOMING_MESSAGE, &Z_ReceiveAfIncomingMessage },
// { AREQ_STATE_CHANGE_IND, &Z_ReceiveStateChange },
{ AREQ_END_DEVICE_ANNCE_IND, &Z_ReceiveEndDeviceAnnonce },
{ AREQ_END_DEVICE_TC_DEV_IND, &Z_ReceiveTCDevInd },
{ AREQ_PERMITJOIN_OPEN_XX, &Z_ReceivePermitJoinStatus },
{ AREQ_ZDO_NODEDESCRSP, &Z_ReceiveNodeDesc },
{ AREQ_ZDO_ACTIVEEPRSP, &Z_ReceiveActiveEp },
{ AREQ_ZDO_IEEE_ADDR_RSP, &Z_ReceiveIEEEAddr },
{ AREQ_ZDO_BIND_RSP, &Z_BindRsp },
{ AREQ_ZDO_UNBIND_RSP, &Z_UnbindRsp },
{ AREQ_ZDO_MGMT_BIND_RSP, &Z_MgmtBindRsp },
{ { Z_AREQ | Z_AF, AF_DATA_CONFIRM }, &ZNP_DataConfirm }, // 4480
{ { Z_AREQ | Z_AF, AF_INCOMING_MSG }, &ZNP_ReceiveAfIncomingMessage }, // 4481
// { { Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND }, &ZNP_ReceiveStateChange }, // 45C0
{ { Z_AREQ | Z_ZDO, ZDO_END_DEVICE_ANNCE_IND }, &Z_ReceiveEndDeviceAnnonce }, // 45C1
{ { Z_AREQ | Z_ZDO, ZDO_TC_DEV_IND }, &ZNP_ReceiveTCDevInd }, // 45CA
{ { Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND }, &ZNP_ReceivePermitJoinStatus }, // 45CB
{ { Z_AREQ | Z_ZDO, ZDO_NODE_DESC_RSP }, &ZNP_ReceiveNodeDesc }, // 4582
{ { Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP }, &Z_ReceiveActiveEp }, // 4585
{ { Z_AREQ | Z_ZDO, ZDO_IEEE_ADDR_RSP }, &Z_ReceiveIEEEAddr }, // 4581
{ { Z_AREQ | Z_ZDO, ZDO_BIND_RSP }, &ZNP_BindRsp }, // 45A1
{ { Z_AREQ | Z_ZDO, ZDO_UNBIND_RSP }, &ZNP_UnbindRsp }, // 45A2
{ { Z_AREQ | Z_ZDO, ZDO_MGMT_BIND_RSP }, &ZNP_MgmtBindRsp }, // 45B3
};
/*********************************************************************************************\
* Default resolver
\*********************************************************************************************/
int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf) {
int32_t ZNP_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

View File

@ -542,7 +542,7 @@ int32_t ZigbeeProcessInputRaw(class SBuffer &buf) {
// RSTACK
// received just after boot, either because of Power up, hardware reset or RST
Z_EZSP_RSTACK(buf.get8(2));
EZ_RSTACK(buf.get8(2));
EZSP_Serial.from_ack = 0;
EZSP_Serial.to_ack = 0;
@ -555,7 +555,7 @@ int32_t ZigbeeProcessInputRaw(class SBuffer &buf) {
} else if (control_byte == 0xC2) {
// ERROR
Z_EZSP_ERROR(buf.get8(2));
EZ_ERROR(buf.get8(2));
zigbee.active = false; // stop all zigbee activities
} else {
@ -691,6 +691,38 @@ void ZigbeeZCLSend_Raw(uint16_t shortaddr, uint16_t groupaddr, uint16_t clusterI
ZigbeeZNPSend(buf.getBuffer(), buf.len());
#endif // USE_ZIGBEE_ZNP
#ifdef USE_ZIGBEE_EZSP
SBuffer buf(32+len);
buf.add16(EZSP_sendUnicast); // 3400
buf.add8(EMBER_OUTGOING_DIRECT); // 00
buf.add16(shortaddr); // dest addr
// ApsFrame
buf.add16(Z_PROF_HA); // Home Automation profile
buf.add16(clusterId); // cluster
buf.add8(0x01); // srcEp
buf.add8(endpoint); // dstEp
buf.add16(EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY | EMBER_APS_OPTION_RETRY); // APS frame
buf.add16(groupaddr); // groupId
buf.add8(transacId);
// end of ApsFrame
buf.add8(0x01); // tag TODO
buf.add8(3 + len + (manuf ? 2 : 0));
buf.add8((needResponse ? 0x00 : 0x10) | (clusterSpecific ? 0x01 : 0x00) | (manuf ? 0x04 : 0x00)); // Frame Control Field
if (manuf) {
buf.add16(manuf); // add Manuf Id if not null
}
buf.add8(transacId); // Transaction Sequance Number
buf.add8(cmdId);
if (len > 0) {
buf.addBuffer(msg, len); // add the payload
}
ZigbeeEZSPSendCmd(buf.buf(), buf.len(), true);
#endif // USE_ZIGBEE_EZSP
}
#endif // USE_ZIGBEE

View File

@ -64,10 +64,16 @@ void ZigbeeInit(void)
Settings.zb_precfgkey_h = USE_ZIGBEE_PRECFGKEY_H;
Settings.zb_pan_id = USE_ZIGBEE_PANID;
Settings.zb_channel = USE_ZIGBEE_CHANNEL;
Settings.zb_free_byte = 0;
Settings.zb_txradio_dbm = USE_ZIGBEE_TXRADIO_DBM;
}
// update commands with the current settings
Z_UpdateConfig(Settings.zb_channel, Settings.zb_pan_id, Settings.zb_ext_panid, Settings.zb_precfgkey_l, Settings.zb_precfgkey_h);
#ifdef USE_ZIGBEE_ZNP
ZNP_UpdateConfig(Settings.zb_channel, Settings.zb_pan_id, Settings.zb_ext_panid, Settings.zb_precfgkey_l, Settings.zb_precfgkey_h);
#endif
#ifdef USE_ZIGBEE_EZSP
EZ_UpdateConfig(Settings.zb_channel, Settings.zb_pan_id, Settings.zb_ext_panid, Settings.zb_precfgkey_l, Settings.zb_precfgkey_h, Settings.zb_txradio_dbm);
#endif
ZigbeeInitSerial();
}
@ -1018,6 +1024,7 @@ void CmndZbConfig(void) {
uint64_t zb_ext_panid = Settings.zb_ext_panid;
uint64_t zb_precfgkey_l = Settings.zb_precfgkey_l;
uint64_t zb_precfgkey_h = Settings.zb_precfgkey_h;
uint8_t zb_txradio_dbm = Settings.zb_txradio_dbm;
// if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
RemoveAllSpaces(XdrvMailbox.data);
@ -1043,18 +1050,23 @@ void CmndZbConfig(void) {
// KeyH
const JsonVariant &val_key_h = GetCaseInsensitive(json, PSTR("KeyH"));
if (nullptr != &val_key_h) { zb_precfgkey_h = strtoull(val_key_h.as<const char*>(), nullptr, 0); }
// TxRadio dBm
const JsonVariant &val_txradio = GetCaseInsensitive(json, PSTR("TxRadio"));
if (nullptr != &val_txradio) { zb_txradio_dbm = strToUInt(val_txradio); }
// Check if a parameter was changed after all
if ( (zb_channel != Settings.zb_channel) ||
(zb_pan_id != Settings.zb_pan_id) ||
(zb_ext_panid != Settings.zb_ext_panid) ||
(zb_precfgkey_l != Settings.zb_precfgkey_l) ||
(zb_precfgkey_h != Settings.zb_precfgkey_h) ) {
(zb_precfgkey_h != Settings.zb_precfgkey_h) ||
(zb_txradio_dbm != Settings.zb_txradio_dbm) ) {
Settings.zb_channel = zb_channel;
Settings.zb_pan_id = zb_pan_id;
Settings.zb_ext_panid = zb_ext_panid;
Settings.zb_precfgkey_l = zb_precfgkey_l;
Settings.zb_precfgkey_h = zb_precfgkey_h;
Settings.zb_txradio_dbm = zb_txradio_dbm;
restart_flag = 2; // save and reboot
}
}
@ -1074,10 +1086,12 @@ void CmndZbConfig(void) {
",\"ExtPanID\":\"%s\""
",\"KeyL\":\"%s\""
",\"KeyH\":\"%s\""
",\"TxRadio\":%d"
"}}"),
zb_channel, zb_pan_id,
hex_ext_panid,
hex_precfgkey_l, hex_precfgkey_h);
hex_precfgkey_l, hex_precfgkey_h,
zb_txradio_dbm);
}
/*********************************************************************************************\