|
|
@ -9,8 +9,6 @@
|
|
|
|
#include <zigbee/zigbee_app_utils.h>
|
|
|
|
#include <zigbee/zigbee_app_utils.h>
|
|
|
|
#include <zb_nrf_platform.h>
|
|
|
|
#include <zb_nrf_platform.h>
|
|
|
|
|
|
|
|
|
|
|
|
#include <zigbee/zigbee_fota.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <zephyr/sys/reboot.h>
|
|
|
|
#include <zephyr/sys/reboot.h>
|
|
|
|
|
|
|
|
|
|
|
|
#include "switch.h"
|
|
|
|
#include "switch.h"
|
|
|
@ -18,6 +16,7 @@
|
|
|
|
LOG_MODULE_REGISTER(app, LOG_LEVEL_INF);
|
|
|
|
LOG_MODULE_REGISTER(app, LOG_LEVEL_INF);
|
|
|
|
|
|
|
|
|
|
|
|
#define INFO_ENDPOINT 64
|
|
|
|
#define INFO_ENDPOINT 64
|
|
|
|
|
|
|
|
|
|
|
|
#define SW0_EP 1
|
|
|
|
#define SW0_EP 1
|
|
|
|
#define SW1_EP 2
|
|
|
|
#define SW1_EP 2
|
|
|
|
#define SW2_EP 3
|
|
|
|
#define SW2_EP 3
|
|
|
@ -45,21 +44,22 @@ struct app_nvram {
|
|
|
|
enum zb_zcl_on_off_switch_configuration_switch_actions_e actions[4];
|
|
|
|
enum zb_zcl_on_off_switch_configuration_switch_actions_e actions[4];
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Zigbee device application context storage. */
|
|
|
|
/* Zigbee device application context storage. */
|
|
|
|
static struct app_static app_static = {
|
|
|
|
static struct app_static app_static = {
|
|
|
|
.basic_attr = {
|
|
|
|
.basic_attr = {
|
|
|
|
.zcl_version = ZB_ZCL_VERSION,
|
|
|
|
.zcl_version = ZB_ZCL_VERSION,
|
|
|
|
.power_source = ZB_ZCL_BASIC_POWER_SOURCE_MAINS_SINGLE_PHASE,
|
|
|
|
|
|
|
|
.ph_env = ZB_ZCL_BASIC_ENV_UNSPECIFIED,
|
|
|
|
|
|
|
|
.app_version = 1,
|
|
|
|
.app_version = 1,
|
|
|
|
.stack_version = 10,
|
|
|
|
.stack_version = 10,
|
|
|
|
.hw_version = 1,
|
|
|
|
.hw_version = 1,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.power_source = ZB_ZCL_BASIC_POWER_SOURCE_MAINS_SINGLE_PHASE,
|
|
|
|
|
|
|
|
.ph_env = ZB_ZCL_BASIC_ENV_UNSPECIFIED,
|
|
|
|
|
|
|
|
|
|
|
|
.mf_name = {0},
|
|
|
|
.mf_name = {0},
|
|
|
|
.model_id = {0},
|
|
|
|
.model_id = {0},
|
|
|
|
.date_code = {0},
|
|
|
|
.date_code = {0},
|
|
|
|
.location_id = {0},
|
|
|
|
.location_id = {0},
|
|
|
|
|
|
|
|
.sw_ver = {0},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
.identify_attr = {
|
|
|
|
.identify_attr = {
|
|
|
|
.identify_time = ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE,
|
|
|
|
.identify_time = ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE,
|
|
|
@ -108,7 +108,12 @@ ZB_DECLARE_SW_EP(sw1_ep, SW1_EP, app_ram.state_attributes[1], app_static.types[1
|
|
|
|
ZB_DECLARE_SW_EP(sw2_ep, SW2_EP, app_ram.state_attributes[2], app_static.types[2], app_nvram.actions[2]);
|
|
|
|
ZB_DECLARE_SW_EP(sw2_ep, SW2_EP, app_ram.state_attributes[2], app_static.types[2], app_nvram.actions[2]);
|
|
|
|
ZB_DECLARE_SW_EP(sw3_ep, SW3_EP, app_ram.state_attributes[3], app_static.types[3], app_nvram.actions[3]);
|
|
|
|
ZB_DECLARE_SW_EP(sw3_ep, SW3_EP, app_ram.state_attributes[3], app_static.types[3], app_nvram.actions[3]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_ZIGBEE_FOTA
|
|
|
|
|
|
|
|
#include <zigbee/zigbee_fota.h>
|
|
|
|
|
|
|
|
#include <zephyr/dfu/mcuboot.h>
|
|
|
|
extern zb_af_endpoint_desc_t zigbee_fota_client_ep;
|
|
|
|
extern zb_af_endpoint_desc_t zigbee_fota_client_ep;
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
ZBOSS_DECLARE_DEVICE_CTX_EP_VA(
|
|
|
|
ZBOSS_DECLARE_DEVICE_CTX_EP_VA(
|
|
|
|
zigbee_ctx,
|
|
|
|
zigbee_ctx,
|
|
|
@ -117,7 +122,10 @@ ZBOSS_DECLARE_DEVICE_CTX_EP_VA(
|
|
|
|
&sw1_ep,
|
|
|
|
&sw1_ep,
|
|
|
|
&sw2_ep,
|
|
|
|
&sw2_ep,
|
|
|
|
&sw3_ep,
|
|
|
|
&sw3_ep,
|
|
|
|
&zigbee_fota_client_ep);
|
|
|
|
#ifdef CONFIG_ZIGBEE_FOTA
|
|
|
|
|
|
|
|
&zigbee_fota_client_ep,
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
static const struct gpio_dt_spec network_led = GPIO_DT_SPEC_GET(DT_NODELABEL(network_led), gpios);
|
|
|
|
static const struct gpio_dt_spec network_led = GPIO_DT_SPEC_GET(DT_NODELABEL(network_led), gpios);
|
|
|
|
static const struct gpio_dt_spec sw[4] = {
|
|
|
|
static const struct gpio_dt_spec sw[4] = {
|
|
|
@ -137,11 +145,26 @@ static void zigbee_init_clusters(void)
|
|
|
|
char model[] = "jamie";
|
|
|
|
char model[] = "jamie";
|
|
|
|
ZB_ZCL_SET_STRING_VAL(app_static.basic_attr.model_id, model, ZB_ZCL_STRING_CONST_SIZE(model));
|
|
|
|
ZB_ZCL_SET_STRING_VAL(app_static.basic_attr.model_id, model, ZB_ZCL_STRING_CONST_SIZE(model));
|
|
|
|
|
|
|
|
|
|
|
|
char date[] = "jamie";
|
|
|
|
char date[] = __DATE__;
|
|
|
|
ZB_ZCL_SET_STRING_VAL(app_static.basic_attr.date_code, date, ZB_ZCL_STRING_CONST_SIZE(date));
|
|
|
|
ZB_ZCL_SET_STRING_VAL(app_static.basic_attr.date_code, date, ZB_ZCL_STRING_CONST_SIZE(date));
|
|
|
|
|
|
|
|
|
|
|
|
char location[] = "jamie";
|
|
|
|
char location[] = "UNKNOWN";
|
|
|
|
ZB_ZCL_SET_STRING_VAL(app_static.basic_attr.date_code, location, ZB_ZCL_STRING_CONST_SIZE(location));
|
|
|
|
ZB_ZCL_SET_STRING_VAL(app_static.basic_attr.location_id, location, ZB_ZCL_STRING_CONST_SIZE(location));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char build_id[] = "debug";
|
|
|
|
|
|
|
|
ZB_ZCL_SET_STRING_VAL(app_static.basic_attr.sw_ver, build_id, ZB_ZCL_STRING_CONST_SIZE(build_id));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(size_t i = 0; i < 4; i++){
|
|
|
|
|
|
|
|
app_ram.states[i] = gpio_pin_get_dt(&sw[i]);
|
|
|
|
|
|
|
|
switch(app_nvram.actions[i]){
|
|
|
|
|
|
|
|
case ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TYPE1:
|
|
|
|
|
|
|
|
app_ram.state_attributes[i].on_off = app_ram.states[i];
|
|
|
|
|
|
|
|
case ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TYPE2:
|
|
|
|
|
|
|
|
app_ram.state_attributes[i].on_off = !app_ram.states[i];
|
|
|
|
|
|
|
|
case ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TOGGLE:
|
|
|
|
|
|
|
|
app_ram.state_attributes[i].on_off = ZB_ZCL_ON_OFF_ON_OFF_DEFAULT_VALUE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct queue_item_s {
|
|
|
|
typedef struct queue_item_s {
|
|
|
@ -206,13 +229,29 @@ static void configure_gpio(void)
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
void zboss_signal_handler(zb_bufid_t bufid)
|
|
|
|
void zboss_signal_handler(zb_bufid_t bufid)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
#ifdef CONFIG_ZIGBEE_FOTA
|
|
|
|
zigbee_fota_signal_handler(bufid);
|
|
|
|
zigbee_fota_signal_handler(bufid);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
gpio_pin_toggle_dt(&network_led);
|
|
|
|
gpio_pin_toggle_dt(&network_led);
|
|
|
|
|
|
|
|
|
|
|
|
zb_zdo_app_signal_hdr_t *sig_handler = NULL;
|
|
|
|
zb_zdo_app_signal_hdr_t *sig_handler = NULL;
|
|
|
|
zb_zdo_app_signal_type_t sig = zb_get_app_signal(bufid, &sig_handler);
|
|
|
|
zb_zdo_app_signal_type_t sig = zb_get_app_signal(bufid, &sig_handler);
|
|
|
|
|
|
|
|
zb_ret_t status = zb_buf_get_status(sig);
|
|
|
|
|
|
|
|
|
|
|
|
switch (sig) {
|
|
|
|
switch (sig) {
|
|
|
|
|
|
|
|
case ZB_ZDO_SIGNAL_PRODUCTION_CONFIG_READY:
|
|
|
|
|
|
|
|
LOG_INF("Production config found");
|
|
|
|
|
|
|
|
if (status != RET_OK) {
|
|
|
|
|
|
|
|
/* Production config is not present or invalid */
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
zb_uint32_t app_data_length = zb_buf_len(bufid) - sizeof(zb_zdo_app_signal_hdr_t);
|
|
|
|
|
|
|
|
if (app_data_length != 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* Process production config */
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
/* Call default signal handler. */
|
|
|
|
/* Call default signal handler. */
|
|
|
|
ZB_ERROR_CHECK(zigbee_default_signal_handler(bufid));
|
|
|
|
ZB_ERROR_CHECK(zigbee_default_signal_handler(bufid));
|
|
|
@ -267,6 +306,10 @@ zb_uint16_t app_nvram_size(void){
|
|
|
|
* used to pass received data.
|
|
|
|
* used to pass received data.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static void zcl_device_cb(zb_bufid_t bufid) {
|
|
|
|
static void zcl_device_cb(zb_bufid_t bufid) {
|
|
|
|
|
|
|
|
#ifdef CONFIG_ZIGBEE_FOTA
|
|
|
|
|
|
|
|
zigbee_fota_zcl_cb(bufid);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
zb_uint8_t cluster_id;
|
|
|
|
zb_uint8_t cluster_id;
|
|
|
|
zb_uint8_t attr_id;
|
|
|
|
zb_uint8_t attr_id;
|
|
|
|
zb_zcl_device_callback_param_t *device_cb_param = ZB_BUF_GET_PARAM(bufid, zb_zcl_device_callback_param_t);
|
|
|
|
zb_zcl_device_callback_param_t *device_cb_param = ZB_BUF_GET_PARAM(bufid, zb_zcl_device_callback_param_t);
|
|
|
@ -285,28 +328,37 @@ static void zcl_device_cb(zb_bufid_t bufid) {
|
|
|
|
case ZB_ZCL_ATTR_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_ID:
|
|
|
|
case ZB_ZCL_ATTR_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_ID:
|
|
|
|
uint8_t value = device_cb_param->cb_param.set_attr_value_param.values.data8;
|
|
|
|
uint8_t value = device_cb_param->cb_param.set_attr_value_param.values.data8;
|
|
|
|
uint8_t ep = device_cb_param->endpoint;
|
|
|
|
uint8_t ep = device_cb_param->endpoint;
|
|
|
|
uint8_t sw = ep - 1;
|
|
|
|
uint8_t sw = 0xFF;
|
|
|
|
zb_bool_t sw_val = app_ram.states[sw];
|
|
|
|
for(uint8_t i = 0; i < 4; i++) {
|
|
|
|
switch(app_nvram.actions[sw]) {
|
|
|
|
if(sw_ep[i] == ep){
|
|
|
|
case ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TYPE1:
|
|
|
|
sw = i;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TYPE2:
|
|
|
|
}
|
|
|
|
sw_val = !sw_val;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TOGGLE:
|
|
|
|
|
|
|
|
sw_val = app_ram.state_attributes[sw].on_off;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(sw != 0xFF) {
|
|
|
|
ZB_SCHEDULE_APP_CALLBACK(set_sw, ((sw & 0x0F) << 4) + ((sw_val & 0x0F) << 0));
|
|
|
|
zb_bool_t sw_val = app_ram.states[sw];
|
|
|
|
|
|
|
|
switch(app_nvram.actions[sw]) {
|
|
|
|
LOG_INF("New switch actions: %d - %d", ep, value);
|
|
|
|
case ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TYPE1:
|
|
|
|
zb_ret_t err = zb_nvram_write_dataset(ZB_NVRAM_APP_DATA1);
|
|
|
|
break;
|
|
|
|
if(err){
|
|
|
|
case ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TYPE2:
|
|
|
|
LOG_ERR("Failed to write app1 nvram: %e", err);
|
|
|
|
sw_val = !sw_val;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TOGGLE:
|
|
|
|
|
|
|
|
sw_val = app_ram.state_attributes[sw].on_off;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ZB_SCHEDULE_APP_CALLBACK(set_sw, ((sw & 0x0F) << 4) + ((sw_val & 0x0F) << 0));
|
|
|
|
|
|
|
|
LOG_INF("New switch actions: %d - %d", ep, value);
|
|
|
|
|
|
|
|
zb_ret_t err = zb_nvram_write_dataset(ZB_NVRAM_APP_DATA1);
|
|
|
|
|
|
|
|
if(err){
|
|
|
|
|
|
|
|
LOG_ERR("Failed to write app1 nvram: %d", err);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
LOG_INF("Wrote app1 nvram");
|
|
|
|
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
LOG_INF("Wrote app1 nvram");
|
|
|
|
LOG_ERR("Got on off switch configuration for unknown switch endpoint: %d", ep);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
LOG_WRN("Unhandled on_off_switch_cfg attribute ID: %d", attr_id);
|
|
|
|
LOG_WRN("Unhandled on_off_switch_cfg attribute ID: %d", attr_id);
|
|
|
@ -316,20 +368,18 @@ static void zcl_device_cb(zb_bufid_t bufid) {
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
LOG_WRN("Unhandled cluster ID: %d", cluster_id);
|
|
|
|
LOG_WRN("Unhandled cluster ID: %d", cluster_id);
|
|
|
|
device_cb_param->status = RET_NOT_IMPLEMENTED;
|
|
|
|
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
LOG_WRN("Unhandled callback ID: %d", device_cb_param->device_cb_id);
|
|
|
|
LOG_WRN("Unhandled callback ID: %d", device_cb_param->device_cb_id);
|
|
|
|
device_cb_param->status = RET_NOT_IMPLEMENTED;
|
|
|
|
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
zigbee_fota_zcl_cb(bufid);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_ZIGBEE_FOTA
|
|
|
|
/**@brief Callback function for handling OTA events.
|
|
|
|
/**@brief Callback function for handling OTA events.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param[in] *evt Structure containing event information
|
|
|
|
* @param[in] *evt Structure containing event information
|
|
|
@ -346,6 +396,7 @@ static void ota_evt_handler(const struct zigbee_fota_evt *evt)
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
int main(void)
|
|
|
|
int main(void)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -354,19 +405,20 @@ int main(void)
|
|
|
|
/* Initialize */
|
|
|
|
/* Initialize */
|
|
|
|
configure_gpio();
|
|
|
|
configure_gpio();
|
|
|
|
|
|
|
|
|
|
|
|
/* Register device callback */
|
|
|
|
zigbee_init_clusters();
|
|
|
|
ZB_ZCL_REGISTER_DEVICE_CB(zcl_device_cb);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Register device context (endpoints). */
|
|
|
|
/* Register device context (endpoints). */
|
|
|
|
ZB_AF_REGISTER_DEVICE_CTX(&zigbee_ctx);
|
|
|
|
ZB_AF_REGISTER_DEVICE_CTX(&zigbee_ctx);
|
|
|
|
|
|
|
|
|
|
|
|
/* Initialize Zigbee FOTA download service. */
|
|
|
|
/* Register device callback */
|
|
|
|
zigbee_fota_init(ota_evt_handler);
|
|
|
|
ZB_ZCL_REGISTER_DEVICE_CB(zcl_device_cb);
|
|
|
|
|
|
|
|
|
|
|
|
zigbee_init_clusters();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ZB_AF_SET_IDENTIFY_NOTIFICATION_HANDLER(INFO_ENDPOINT, identify_cb);
|
|
|
|
ZB_AF_SET_IDENTIFY_NOTIFICATION_HANDLER(INFO_ENDPOINT, identify_cb);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_ZIGBEE_FOTA
|
|
|
|
|
|
|
|
zigbee_fota_init(ota_evt_handler);
|
|
|
|
ZB_AF_SET_IDENTIFY_NOTIFICATION_HANDLER(CONFIG_ZIGBEE_FOTA_ENDPOINT, identify_cb);
|
|
|
|
ZB_AF_SET_IDENTIFY_NOTIFICATION_HANDLER(CONFIG_ZIGBEE_FOTA_ENDPOINT, identify_cb);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
zb_nvram_register_app1_read_cb(app_nvram_read);
|
|
|
|
zb_nvram_register_app1_read_cb(app_nvram_read);
|
|
|
|
zb_nvram_register_app1_write_cb(app_nvram_write, app_nvram_size);
|
|
|
|
zb_nvram_register_app1_write_cb(app_nvram_write, app_nvram_size);
|
|
|
@ -375,9 +427,10 @@ int main(void)
|
|
|
|
|
|
|
|
|
|
|
|
LOG_INF("Zigbee Stack Initialized");
|
|
|
|
LOG_INF("Zigbee Stack Initialized");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_ZIGBEE_FOTA
|
|
|
|
boot_write_img_confirmed();
|
|
|
|
boot_write_img_confirmed();
|
|
|
|
|
|
|
|
|
|
|
|
LOG_INF("Confirmed firmware");
|
|
|
|
LOG_INF("Confirmed firmware");
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
while(true) {
|
|
|
|
while(true) {
|
|
|
|
queue_item_t* item = (queue_item_t*) k_queue_get(&switch_queue, K_FOREVER);
|
|
|
|
queue_item_t* item = (queue_item_t*) k_queue_get(&switch_queue, K_FOREVER);
|
|
|
|