|
|
|
@ -35,7 +35,10 @@ struct app_static {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct app_ram {
|
|
|
|
|
zb_zcl_on_off_attrs_t states[4];
|
|
|
|
|
struct gpio_callback sw_cb[4];
|
|
|
|
|
zb_uint8_t states[4];
|
|
|
|
|
uint64_t last[4];
|
|
|
|
|
zb_zcl_on_off_attrs_t state_attributes[4];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct app_nvram {
|
|
|
|
@ -77,6 +80,13 @@ static struct app_ram app_ram = {
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
.state_attributes = {
|
|
|
|
|
{.on_off = 0},
|
|
|
|
|
{.on_off = 0},
|
|
|
|
|
{.on_off = 0},
|
|
|
|
|
{.on_off = 0},
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct app_nvram app_nvram = {
|
|
|
|
@ -93,10 +103,10 @@ 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]);
|
|
|
|
|
ZB_DECLARE_SW_EP(sw0_ep, SW0_EP, app_ram.state_attributes[0], app_static.types[0], app_nvram.actions[0]);
|
|
|
|
|
ZB_DECLARE_SW_EP(sw1_ep, SW1_EP, app_ram.state_attributes[1], app_static.types[1], app_nvram.actions[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(sw3_ep, SW3_EP, app_ram.state_attributes[3], app_static.types[3], app_nvram.actions[3]);
|
|
|
|
|
|
|
|
|
|
extern zb_af_endpoint_desc_t zigbee_fota_client_ep;
|
|
|
|
|
|
|
|
|
@ -116,10 +126,7 @@ static const struct gpio_dt_spec sw[4] = {
|
|
|
|
|
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};
|
|
|
|
|
#define SW_DEBOUNCE_MS 125
|
|
|
|
|
|
|
|
|
|
/**@brief Function for initializing all clusters attributes. */
|
|
|
|
|
static void zigbee_init_clusters(void)
|
|
|
|
@ -151,6 +158,7 @@ void sw_handler(size_t i) {
|
|
|
|
|
k_queue_alloc_append(&switch_queue, item);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: do this better
|
|
|
|
|
void sw0_handler(const struct device *dev, struct gpio_callback *cb, gpio_port_pins_t pins) {
|
|
|
|
|
sw_handler(0);
|
|
|
|
|
}
|
|
|
|
@ -186,9 +194,9 @@ static void configure_gpio(void)
|
|
|
|
|
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();
|
|
|
|
|
gpio_init_callback(&(app_ram.sw_cb[i]), sw_handlers[i], BIT(sw[i].pin));
|
|
|
|
|
err = gpio_add_callback(sw[i].port, &(app_ram.sw_cb[i]));
|
|
|
|
|
app_ram.last[i] = k_uptime_get();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -277,6 +285,21 @@ static void zcl_device_cb(zb_bufid_t bufid) {
|
|
|
|
|
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;
|
|
|
|
|
uint8_t sw = ep - 1;
|
|
|
|
|
zb_bool_t sw_val = app_ram.states[sw];
|
|
|
|
|
switch(app_nvram.actions[sw]) {
|
|
|
|
|
case ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TYPE1:
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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){
|
|
|
|
@ -303,6 +326,8 @@ static void zcl_device_cb(zb_bufid_t bufid) {
|
|
|
|
|
device_cb_param->status = RET_NOT_IMPLEMENTED;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
zigbee_fota_zcl_cb(bufid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**@brief Callback function for handling OTA events.
|
|
|
|
@ -337,8 +362,6 @@ int main(void)
|
|
|
|
|
|
|
|
|
|
/* Initialize Zigbee FOTA download service. */
|
|
|
|
|
zigbee_fota_init(ota_evt_handler);
|
|
|
|
|
/* Register callback for handling ZCL commands. */
|
|
|
|
|
ZB_ZCL_REGISTER_DEVICE_CB(zigbee_fota_zcl_cb);
|
|
|
|
|
|
|
|
|
|
zigbee_init_clusters();
|
|
|
|
|
|
|
|
|
@ -359,14 +382,33 @@ int main(void)
|
|
|
|
|
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_bool_t val = gpio_pin_get_dt(&sw[item->sw]);
|
|
|
|
|
if((item->time - app_ram.last[item->sw] > SW_DEBOUNCE_MS) && (val != app_ram.states[item->sw])) {
|
|
|
|
|
app_ram.last[item->sw] = item->time;
|
|
|
|
|
app_ram.states[item->sw] = val;
|
|
|
|
|
|
|
|
|
|
zb_bool_t attrib_val = val;
|
|
|
|
|
switch(app_nvram.actions[item->sw]) {
|
|
|
|
|
case ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TYPE1:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TYPE2:
|
|
|
|
|
attrib_val = !val;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
ZB_SCHEDULE_APP_CALLBACK(set_sw, ((item->sw & 0x0F) << 4) + ((val & 0x0F) << 0));
|
|
|
|
|
case ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TOGGLE:
|
|
|
|
|
attrib_val = !app_ram.state_attributes[item->sw].on_off;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LOG_INF("Queue input %d to %d change", item->sw, val);
|
|
|
|
|
ZB_SCHEDULE_APP_CALLBACK(set_sw, ((item->sw & 0x0F) << 4) + ((attrib_val & 0x0F) << 0));
|
|
|
|
|
|
|
|
|
|
if(val) {
|
|
|
|
|
|
|
|
|
|
LOG_INF("Input %d rising edge", item->sw);
|
|
|
|
|
} else {
|
|
|
|
|
LOG_INF("Input %d falling edge", item->sw);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
k_free(item);
|
|
|
|
|
}
|
|
|
|
|