#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "factory_reset.h" #include "prst_zb_attrs.h" #include "prst_zb_endpoint_defs.h" #include "prst_zb_soil_moisture_defs.h" LOG_MODULE_REGISTER(app, CONFIG_LOG_DEFAULT_LEVEL); static struct zb_device_ctx dev_ctx; static prst_sensors_t sensors; static void led_flashing_cb(struct k_timer *timer) { prst_led_toggle(); } K_TIMER_DEFINE(led_flashing_timer, led_flashing_cb, /*stop_fn=*/NULL); ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST( identify_attr_list, &dev_ctx.identify_attr.identify_time); ZB_ZCL_DECLARE_BASIC_ATTRIB_LIST_EXT( 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_DECLARE_TEMP_MEASUREMENT_ATTRIB_LIST(temp_measurement_attr_list, &dev_ctx.temp_measure_attrs.measure_value, &dev_ctx.temp_measure_attrs.min_measure_value, &dev_ctx.temp_measure_attrs.max_measure_value, &dev_ctx.temp_measure_attrs.tolerance); ZB_ZCL_DECLARE_REL_HUMIDITY_MEASUREMENT_ATTRIB_LIST( rel_humi_attr_list, &dev_ctx.rel_humidity_attrs.rel_humidity, &dev_ctx.rel_humidity_attrs.min_val, &dev_ctx.rel_humidity_attrs.max_val); // https://devzone.nordicsemi.com/f/nordic-q-a/85315/zboss-declare-power-config-attribute-list-for-battery-bat_num #define bat_num ZB_ZCL_DECLARE_POWER_CONFIG_BATTERY_ATTRIB_LIST_EXT( batt_attr_list, &dev_ctx.batt_attrs.voltage, /*battery_size=*/ZB_ZCL_POWER_CONFIG_BATTERY_SIZE_OTHER, /*battery_quantity=*/1, /*battery_rated_voltage=*/NULL, /*battery_alarm_mask=*/NULL, /*battery_voltage_min_threshold=*/NULL, /*battery_percentage_remaining=*/&dev_ctx.batt_attrs.percentage, /*battery_voltage_threshold1=*/NULL, /*battery_voltage_threshold2=*/NULL, /*battery_voltage_threshold3=*/NULL, /*battery_percentage_min_threshold=*/NULL, /*battery_percentage_threshold1=*/NULL, /*battery_percentage_threshold2=*/NULL, /*battery_percentage_threshold3=*/NULL, /*battery_alarm_state=*/NULL); PRST_ZB_ZCL_DECLARE_SOIL_MOISTURE_ATTRIB_LIST( soil_moisture_attr_list, &dev_ctx.soil_moisture_attrs.percentage); ZB_ZCL_DECLARE_ILLUMINANCE_MEASUREMENT_ATTRIB_LIST( illuminance_attr_list, /*value=*/&dev_ctx.illuminance_attrs.log_lux, /*min_value=*/NULL, /*max_value*/ NULL); PRST_ZB_DECLARE_CLUSTER_LIST( app_template_clusters, basic_attr_list, identify_attr_list, temp_measurement_attr_list, rel_humi_attr_list, batt_attr_list, soil_moisture_attr_list, illuminance_attr_list); PRST_ZB_DECLARE_ENDPOINT( app_template_ep, PRST_ZIGBEE_ENDPOINT, app_template_clusters); ZBOSS_DECLARE_DEVICE_CTX_1_EP( app_template_ctx, app_template_ep); void zboss_signal_handler(zb_bufid_t bufid) { // See zigbee_default_signal_handler() for all available signals. zb_zdo_app_signal_type_t sig = zb_get_app_signal(bufid, /*sg_p=*/NULL); zb_ret_t status = ZB_GET_APP_SIGNAL_STATUS(bufid); switch (sig) { case ZB_BDB_SIGNAL_STEERING: // New network. case ZB_BDB_SIGNAL_DEVICE_REBOOT: { // Previously joined network. LOG_DBG("Steering complete. Status: %d", status); prst_led_flash(/*times=*/3); if (status == RET_OK) { k_timer_stop(&led_flashing_timer); prst_led_off(); } break; } case ZB_ZDO_SIGNAL_SKIP_STARTUP: case ZB_ZDO_SIGNAL_LEAVE: { LOG_DBG("Will restart flashing"); k_timer_start(&led_flashing_timer, K_NO_WAIT, K_SECONDS(1)); break; } } ZB_ERROR_CHECK(zigbee_default_signal_handler(bufid)); if (bufid) { zb_buf_free(bufid); } } void update_sensors_cb(zb_uint8_t arg) { LOG_INF("Updating sensors"); ZB_SCHEDULE_APP_ALARM(update_sensors_cb, /*param=*/0, ZB_TIME_ONE_SECOND * CONFIG_PRST_ZB_SLEEP_DURATION_SEC); if (prst_sensors_read_all(&sensors)) { LOG_ERR("Unable to read sensors"); return; } // Battery voltage in units of 100 mV. uint8_t batt_voltage = sensors.batt.adc_read.millivolts / 100; prst_zb_set_attr_value(ZB_ZCL_CLUSTER_ID_POWER_CONFIG, ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_ID, &batt_voltage); // Battery percentage in units of 0.5%. zb_uint8_t batt_percentage = 2 * 100 * sensors.batt.percentage; prst_zb_set_attr_value(ZB_ZCL_CLUSTER_ID_POWER_CONFIG, ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ID, &batt_percentage); // Temperature in units of 0.01 degrees Celcius. zb_int16_t temperature_value = 100 * sensors.shtc3.temp_c; prst_zb_set_attr_value(ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, &temperature_value); // Relative humidity in units of 0.01%. zb_int16_t rel_humi = 100 * 100 * sensors.shtc3.rel_humi; prst_zb_set_attr_value(ZB_ZCL_CLUSTER_ID_REL_HUMIDITY_MEASUREMENT, ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_VALUE_ID, &rel_humi); // Soil moisture in units of 0.01%. zb_int16_t soil_moisture = 100 * 100 * sensors.soil.percentage; prst_zb_set_attr_value(PRST_ZB_ZCL_ATTR_SOIL_MOISTURE_CLUSTER_ID, PRST_ZB_ZCL_ATTR_SOIL_MOISTURE_VALUE_ID, &soil_moisture); // Illuminance in 10000 * log_10(lux) + 1. zb_int16_t log_lux = 10000 * log10((float)sensors.photo.brightness) + 1; prst_zb_set_attr_value(ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT, ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MEASURED_VALUE_ID, &log_lux); } int main(void) { RET_IF_ERR(prst_adc_init()); RET_IF_ERR(prst_led_init()); RET_IF_ERR(prst_button_init()); RET_IF_ERR(prst_zb_factory_reset_check()); prst_zb_attrs_init(&dev_ctx); ZB_AF_REGISTER_DEVICE_CTX(&app_template_ctx); update_sensors_cb(/*arg=*/0); zb_zdo_pim_set_long_poll_interval( ZB_TIME_ONE_SECOND * CONFIG_PRST_ZB_PARENT_POLL_INTERVAL_SEC); power_down_unused_ram(); RET_IF_ERR(prst_led_flash(2)); k_msleep(100); zigbee_enable(); zigbee_configure_sleepy_behavior(/*enable=*/true); return 0; }