Enabled debug stuff, and added got working to a basic level. Need to add different logic for different switch actions
parent
01c037e4cd
commit
fd8fc112cf
@ -0,0 +1,76 @@
|
||||
#ifndef SWITCH_H
|
||||
#define SWITCH_H
|
||||
|
||||
#define ZB_DECLARE_INFO_EP(ep_name, ep_id, dev_ctx) \
|
||||
\
|
||||
ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST( \
|
||||
ep_name ## _identify_attr_list, \
|
||||
&dev_ctx.identify_attr.identify_time); \
|
||||
\
|
||||
ZB_ZCL_DECLARE_BASIC_ATTRIB_LIST_EXT( \
|
||||
ep_name ## _basic_attr_list, \
|
||||
&dev_ctx.basic_attr.zcl_version, \
|
||||
&dev_ctx.basic_attr.app_version, \
|
||||
&dev_ctx.basic_attr.stack_version, \
|
||||
&dev_ctx.basic_attr.hw_version, \
|
||||
dev_ctx.basic_attr.mf_name, \
|
||||
dev_ctx.basic_attr.model_id, \
|
||||
dev_ctx.basic_attr.date_code, \
|
||||
&dev_ctx.basic_attr.power_source, \
|
||||
dev_ctx.basic_attr.location_id, \
|
||||
&dev_ctx.basic_attr.ph_env, \
|
||||
dev_ctx.basic_attr.sw_ver); \
|
||||
\
|
||||
zb_zcl_cluster_desc_t ep_name ## _clusters[] = { \
|
||||
ZB_ZCL_CLUSTER_DESC(ZB_ZCL_CLUSTER_ID_IDENTIFY, ZB_ZCL_ARRAY_SIZE(ep_name ## _identify_attr_list, zb_zcl_attr_t), (ep_name ## _identify_attr_list), ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_MANUF_CODE_INVALID), \
|
||||
ZB_ZCL_CLUSTER_DESC(ZB_ZCL_CLUSTER_ID_BASIC, ZB_ZCL_ARRAY_SIZE(ep_name ## _basic_attr_list, zb_zcl_attr_t), (ep_name ## _basic_attr_list), ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_MANUF_CODE_INVALID), \
|
||||
}; \
|
||||
\
|
||||
ZB_AF_SIMPLE_DESC_TYPE(2, 0) ep_name ## _desc = { \
|
||||
ep_id, \
|
||||
ZB_AF_HA_PROFILE_ID, \
|
||||
0x0008, \
|
||||
0, \
|
||||
0, \
|
||||
2, \
|
||||
0, \
|
||||
{ \
|
||||
ZB_ZCL_CLUSTER_ID_BASIC, \
|
||||
ZB_ZCL_CLUSTER_ID_IDENTIFY, \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
ZB_AF_DECLARE_ENDPOINT_DESC(ep_name, ep_id, ZB_AF_HA_PROFILE_ID, 0, NULL, ZB_ZCL_ARRAY_SIZE(ep_name ## _clusters, zb_zcl_cluster_desc_t), ep_name ## _clusters, (zb_af_simple_desc_1_1_t *)&ep_name ## _desc, 0, NULL, 0, NULL)
|
||||
|
||||
#define ZB_DECLARE_SW_EP(ep_name, ep_id, state, type, action) \
|
||||
\
|
||||
ZB_ZCL_DECLARE_ON_OFF_ATTRIB_LIST(ep_name ## _attribs, &state.on_off); \
|
||||
ZB_ZCL_DECLARE_ON_OFF_CLIENT_ATTRIB_LIST(ep_name ## _client_attribs); \
|
||||
ZB_ZCL_DECLARE_ON_OFF_SWITCH_CONFIGURATION_ATTRIB_LIST(ep_name ## _config_attribs, &type, &action); \
|
||||
\
|
||||
zb_zcl_cluster_desc_t ep_name ## _clusters[] = { \
|
||||
ZB_ZCL_CLUSTER_DESC(ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_ARRAY_SIZE(ep_name ## _attribs, zb_zcl_attr_t), (ep_name ## _attribs), ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_MANUF_CODE_INVALID), \
|
||||
ZB_ZCL_CLUSTER_DESC(ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_ARRAY_SIZE(ep_name ## _client_attribs, zb_zcl_attr_t), (ep_name ## _client_attribs), ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_MANUF_CODE_INVALID), \
|
||||
ZB_ZCL_CLUSTER_DESC(ZB_ZCL_CLUSTER_ID_ON_OFF_SWITCH_CONFIG, ZB_ZCL_ARRAY_SIZE(ep_name ## _config_attribs, zb_zcl_attr_t), (ep_name ## _config_attribs), ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_MANUF_CODE_INVALID), \
|
||||
}; \
|
||||
\
|
||||
ZB_AF_SIMPLE_DESC_TYPE(2, 1) ep_name ## _desc = { \
|
||||
ep_id, \
|
||||
ZB_AF_HA_PROFILE_ID, \
|
||||
0x0000, \
|
||||
0, \
|
||||
0, \
|
||||
2, \
|
||||
1, \
|
||||
{ \
|
||||
ZB_ZCL_CLUSTER_ID_ON_OFF, \
|
||||
ZB_ZCL_CLUSTER_ID_ON_OFF, \
|
||||
ZB_ZCL_CLUSTER_ID_ON_OFF_SWITCH_CONFIG, \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
ZBOSS_DEVICE_DECLARE_REPORTING_CTX(ep_name ## _rep_ctx, 1); \
|
||||
ZB_AF_DECLARE_ENDPOINT_DESC(ep_name, ep_id, ZB_AF_HA_PROFILE_ID, 0, NULL, ZB_ZCL_ARRAY_SIZE(ep_name ## _clusters, zb_zcl_cluster_desc_t), ep_name ## _clusters, (zb_af_simple_desc_1_1_t *)&ep_name ## _desc, 1, ep_name ## _rep_ctx, 0, NULL)
|
||||
|
||||
|
||||
#endif // SWITCH_H
|
@ -1,31 +1,341 @@
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
|
||||
#include <zboss_api.h>
|
||||
#include <zboss_api_addons.h>
|
||||
#include <zboss_api_zcl_addons.h>
|
||||
#include <zigbee/zigbee_error_handler.h>
|
||||
#include <zigbee/zigbee_app_utils.h>
|
||||
#include <zb_nrf_platform.h>
|
||||
|
||||
#include "switch.h"
|
||||
|
||||
LOG_MODULE_REGISTER(app, LOG_LEVEL_INF);
|
||||
|
||||
#include <zboss_api.h>
|
||||
void zboss_signal_handler(zb_uint8_t param) {
|
||||
#define INFO_ENDPOINT CONFIG_ZIGBEE_SHELL_ENDPOINT
|
||||
#define SW0_EP 1
|
||||
#define SW1_EP 2
|
||||
#define SW2_EP 3
|
||||
#define SW3_EP 4
|
||||
|
||||
const uint8_t sw_ep[4] = {SW0_EP, SW1_EP, SW2_EP, SW3_EP};
|
||||
|
||||
/* Main application customizable context.
|
||||
* Stores all settings and static values.
|
||||
*/
|
||||
struct app_static {
|
||||
zb_zcl_basic_attrs_ext_t basic_attr;
|
||||
zb_zcl_identify_attrs_t identify_attr;
|
||||
enum zb_zcl_on_off_switch_configuration_switch_type_e types[4];
|
||||
};
|
||||
|
||||
struct app_ram {
|
||||
zb_zcl_on_off_attrs_t states[4];
|
||||
};
|
||||
|
||||
struct app_nvram {
|
||||
enum zb_zcl_on_off_switch_configuration_switch_actions_e actions[4];
|
||||
};
|
||||
|
||||
|
||||
/* Zigbee device application context storage. */
|
||||
static struct app_static app_static = {
|
||||
.basic_attr = {
|
||||
.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,
|
||||
.stack_version = 10,
|
||||
.hw_version = 1,
|
||||
|
||||
.mf_name = {0},
|
||||
.model_id = {0},
|
||||
.date_code = {0},
|
||||
.location_id = {0},
|
||||
},
|
||||
.identify_attr = {
|
||||
.identify_time = ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE,
|
||||
},
|
||||
.types = {
|
||||
ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_TYPE_TOGGLE,
|
||||
ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_TYPE_TOGGLE,
|
||||
ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_TYPE_TOGGLE,
|
||||
ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_TYPE_TOGGLE,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
static struct app_ram app_ram = {
|
||||
.states = {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct app_nvram app_nvram = {
|
||||
.actions = {
|
||||
ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TYPE1,
|
||||
ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TYPE1,
|
||||
ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TYPE1,
|
||||
ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TYPE1,
|
||||
},
|
||||
};
|
||||
|
||||
ZB_DECLARE_SIMPLE_DESC(2, 0);
|
||||
ZB_DECLARE_SIMPLE_DESC(2, 1);
|
||||
|
||||
ZB_DECLARE_INFO_EP(info_ep, INFO_ENDPOINT, app_static);
|
||||
|
||||
ZB_DECLARE_SW_EP(sw0_ep, SW0_EP, app_ram.states[0], app_static.types[0], app_nvram.actions[0]);
|
||||
ZB_DECLARE_SW_EP(sw1_ep, SW1_EP, app_ram.states[1], app_static.types[1], app_nvram.actions[1]);
|
||||
ZB_DECLARE_SW_EP(sw2_ep, SW2_EP, app_ram.states[2], app_static.types[2], app_nvram.actions[2]);
|
||||
ZB_DECLARE_SW_EP(sw3_ep, SW3_EP, app_ram.states[3], app_static.types[3], app_nvram.actions[3]);
|
||||
|
||||
ZBOSS_DECLARE_DEVICE_CTX_EP_VA(
|
||||
zigbee_ctx,
|
||||
&info_ep,
|
||||
&sw0_ep,
|
||||
&sw1_ep,
|
||||
&sw2_ep,
|
||||
&sw3_ep);
|
||||
|
||||
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] = {
|
||||
GPIO_DT_SPEC_GET(DT_NODELABEL(sw_0), gpios),
|
||||
GPIO_DT_SPEC_GET(DT_NODELABEL(sw_1), gpios),
|
||||
GPIO_DT_SPEC_GET(DT_NODELABEL(sw_2), gpios),
|
||||
GPIO_DT_SPEC_GET(DT_NODELABEL(sw_3), gpios),
|
||||
};
|
||||
static struct gpio_callback sw_cb[4] = {0};
|
||||
|
||||
#define SW_DEBOUNCE_MS 500
|
||||
static uint64_t sw_last[4] = {0, 0, 0, 0};
|
||||
|
||||
/**@brief Function for initializing all clusters attributes. */
|
||||
static void zigbee_init_clusters(void)
|
||||
{
|
||||
char manufacturer[] = "MetzNet";
|
||||
ZB_ZCL_SET_STRING_VAL(app_static.basic_attr.mf_name, manufacturer, ZB_ZCL_STRING_CONST_SIZE(manufacturer));
|
||||
|
||||
char model[] = "jamie";
|
||||
ZB_ZCL_SET_STRING_VAL(app_static.basic_attr.model_id, model, ZB_ZCL_STRING_CONST_SIZE(model));
|
||||
|
||||
char date[] = "jamie";
|
||||
ZB_ZCL_SET_STRING_VAL(app_static.basic_attr.date_code, date, ZB_ZCL_STRING_CONST_SIZE(date));
|
||||
|
||||
char location[] = "jamie";
|
||||
ZB_ZCL_SET_STRING_VAL(app_static.basic_attr.date_code, location, ZB_ZCL_STRING_CONST_SIZE(location));
|
||||
}
|
||||
|
||||
typedef struct queue_item_s {
|
||||
uint8_t sw;
|
||||
int64_t time;
|
||||
} queue_item_t;
|
||||
|
||||
struct k_queue switch_queue = {0};
|
||||
|
||||
void sw_handler(size_t i) {
|
||||
queue_item_t* item = k_malloc(sizeof(queue_item_t));
|
||||
item->sw = i;
|
||||
item->time = k_uptime_get();
|
||||
k_queue_alloc_append(&switch_queue, item);
|
||||
}
|
||||
|
||||
void sw0_handler(const struct device *dev, struct gpio_callback *cb, gpio_port_pins_t pins) {
|
||||
sw_handler(0);
|
||||
}
|
||||
|
||||
void sw1_handler(const struct device *dev, struct gpio_callback *cb, gpio_port_pins_t pins) {
|
||||
sw_handler(1);
|
||||
}
|
||||
|
||||
void sw2_handler(const struct device *dev, struct gpio_callback *cb, gpio_port_pins_t pins) {
|
||||
sw_handler(2);
|
||||
}
|
||||
|
||||
void sw3_handler(const struct device *dev, struct gpio_callback *cb, gpio_port_pins_t pins) {
|
||||
sw_handler(3);
|
||||
}
|
||||
|
||||
gpio_callback_handler_t sw_handlers[4] = {
|
||||
sw0_handler,
|
||||
sw1_handler,
|
||||
sw2_handler,
|
||||
sw3_handler,
|
||||
};
|
||||
|
||||
static void configure_gpio(void)
|
||||
{
|
||||
int err;
|
||||
err = gpio_pin_configure_dt(&network_led, GPIO_OUTPUT);
|
||||
if(err) {
|
||||
}
|
||||
|
||||
k_queue_init(&switch_queue);
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
err = gpio_pin_configure_dt(&(sw[i]), GPIO_INPUT);
|
||||
err = gpio_pin_interrupt_configure_dt(&(sw[i]), GPIO_INT_EDGE_BOTH);
|
||||
gpio_init_callback(&(sw_cb[i]), sw_handlers[i], BIT(sw[i].pin));
|
||||
err = gpio_add_callback(sw[i].port, &(sw_cb[i]));
|
||||
sw_last[i] = k_uptime_get();
|
||||
}
|
||||
}
|
||||
|
||||
/**@brief Zigbee stack event handler.
|
||||
*
|
||||
* @param[in] bufid Reference to the Zigbee stack buffer used to pass signal.
|
||||
*/
|
||||
void zboss_signal_handler(zb_bufid_t bufid)
|
||||
{
|
||||
gpio_pin_toggle_dt(&network_led);
|
||||
|
||||
zb_zdo_app_signal_hdr_t *sig_handler = NULL;
|
||||
zb_zdo_app_signal_type_t sig = zb_get_app_signal(bufid, &sig_handler);
|
||||
|
||||
switch (sig) {
|
||||
default:
|
||||
/* Call default signal handler. */
|
||||
ZB_ERROR_CHECK(zigbee_default_signal_handler(bufid));
|
||||
break;
|
||||
}
|
||||
|
||||
if (bufid) {
|
||||
zb_buf_free(bufid);
|
||||
}
|
||||
}
|
||||
|
||||
static void identify_cb(zb_bufid_t bufid) {
|
||||
(void)bufid;
|
||||
}
|
||||
|
||||
static void set_sw(zb_uint8_t param) {
|
||||
uint8_t sw = (param & 0xF0) >> 4;
|
||||
uint8_t val = (param & 0x0F);
|
||||
|
||||
ZB_ZCL_SET_ATTRIBUTE(
|
||||
sw_ep[sw],
|
||||
ZB_ZCL_CLUSTER_ID_ON_OFF,
|
||||
ZB_ZCL_CLUSTER_SERVER_ROLE,
|
||||
ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID,
|
||||
(zb_uint8_t *)&val,
|
||||
ZB_FALSE);
|
||||
|
||||
LOG_INF("Set sw %d to %d", sw, val);
|
||||
}
|
||||
|
||||
zb_ret_t app_nvram_write(zb_uint8_t page, zb_uint32_t pos) {
|
||||
LOG_INF("NVRAM_WRITE");
|
||||
return zb_osif_nvram_write(page, pos, (uint8_t*)(&app_nvram), sizeof(struct app_nvram));
|
||||
}
|
||||
|
||||
void app_nvram_read(zb_uint8_t page, zb_uint32_t pos, zb_uint16_t payload_length) {
|
||||
LOG_INF("NVRAM_READ");
|
||||
zb_uint16_t read_len = payload_length;
|
||||
if(payload_length > sizeof(struct app_nvram)) {
|
||||
read_len = sizeof(struct app_nvram);
|
||||
}
|
||||
zb_osif_nvram_read(page, pos, (uint8_t*)(&app_nvram), payload_length);
|
||||
}
|
||||
|
||||
zb_uint16_t app_nvram_size(void){
|
||||
return (zb_uint16_t)(sizeof(struct app_nvram));
|
||||
}
|
||||
|
||||
/**@brief Callback function for handling ZCL commands.
|
||||
*
|
||||
* @param[in] bufid Reference to Zigbee stack buffer
|
||||
* used to pass received data.
|
||||
*/
|
||||
static void zcl_device_cb(zb_bufid_t bufid) {
|
||||
zb_uint8_t cluster_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);
|
||||
|
||||
/* Set default response value. */
|
||||
device_cb_param->status = RET_OK;
|
||||
|
||||
switch(device_cb_param->device_cb_id){
|
||||
case ZB_ZCL_SET_ATTR_VALUE_CB_ID:
|
||||
cluster_id = device_cb_param->cb_param.set_attr_value_param.cluster_id;
|
||||
attr_id = device_cb_param->cb_param.set_attr_value_param.attr_id;
|
||||
|
||||
switch(cluster_id) {
|
||||
case ZB_ZCL_CLUSTER_ID_ON_OFF_SWITCH_CONFIG:
|
||||
switch(attr_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 ep = device_cb_param->endpoint;
|
||||
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: %e", err);
|
||||
} else {
|
||||
LOG_INF("Wrote app1 nvram");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_WRN("Unhandled on_off_switch_cfg attribute ID: %d", attr_id);
|
||||
device_cb_param->status = RET_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_WRN("Unhandled cluster ID: %d", cluster_id);
|
||||
device_cb_param->status = RET_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
LOG_WRN("Unhandled callback ID: %d", device_cb_param->device_cb_id);
|
||||
device_cb_param->status = RET_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
LOG_INF("Starting main");
|
||||
LOG_INF("Starting jamie");
|
||||
|
||||
const struct gpio_dt_spec led_green = GPIO_DT_SPEC_GET(DT_NODELABEL(led0_green), gpios);
|
||||
/* Initialize */
|
||||
configure_gpio();
|
||||
|
||||
gpio_pin_configure_dt(&led_green, GPIO_OUTPUT | GPIO_ACTIVE_LOW);
|
||||
/* Register device callback */
|
||||
ZB_ZCL_REGISTER_DEVICE_CB(zcl_device_cb);
|
||||
|
||||
/* Register device context (endpoints). */
|
||||
ZB_AF_REGISTER_DEVICE_CTX(&zigbee_ctx);
|
||||
|
||||
while(true) {
|
||||
gpio_pin_set_dt(&led_green, 1);
|
||||
zigbee_init_clusters();
|
||||
|
||||
ZB_AF_SET_IDENTIFY_NOTIFICATION_HANDLER(INFO_ENDPOINT, identify_cb);
|
||||
|
||||
zb_nvram_register_app1_read_cb(app_nvram_read);
|
||||
zb_nvram_register_app1_write_cb(app_nvram_write, app_nvram_size);
|
||||
|
||||
zigbee_enable();
|
||||
|
||||
k_msleep(500);
|
||||
LOG_INF("Zigbee Stack Initialized");
|
||||
|
||||
gpio_pin_set_dt(&led_green, 0);
|
||||
while(true) {
|
||||
queue_item_t* item = (queue_item_t*) k_queue_get(&switch_queue, K_FOREVER);
|
||||
if(item != NULL) {
|
||||
int val = gpio_pin_get_dt(&sw[item->sw]);
|
||||
if((item->time - sw_last[item->sw] > SW_DEBOUNCE_MS) && (val != app_ram.states[item->sw].on_off)) {
|
||||
sw_last[item->sw] = item->time;
|
||||
app_ram.states[item->sw].on_off = val;
|
||||
|
||||
ZB_SCHEDULE_APP_CALLBACK(set_sw, ((item->sw & 0x0F) << 4) + ((val & 0x0F) << 0));
|
||||
|
||||
k_msleep(500);
|
||||
LOG_INF("Queue input %d to %d change", item->sw, val);
|
||||
}
|
||||
k_free(item);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue